Форум программистов, компьютерный форум CyberForum.ru

Проверка числа на чётность - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 38, средняя оценка - 4.82
AvengerAlive
5 / 5 / 0
Регистрация: 30.07.2011
Сообщений: 257
29.08.2011, 20:34     Проверка числа на чётность #1
Какой из этих способов работает быстрее
C++
1
if (!(a%2))
или
C++
1
if (!(a&1))
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.08.2011, 20:34     Проверка числа на чётность
Посмотрите здесь:

проверка на чётность C++
C++ Чётность трёх чисел
Проверка на числа C++
Проверка на простоту числа C++
итератор и проверка на чётность\нечётность C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
29.08.2011, 20:37     Проверка числа на чётность #2
На подавляющем числе всевозможных компиляторов — одинаково. В клинических случаях второй быстрее.
AvengerAlive
5 / 5 / 0
Регистрация: 30.07.2011
Сообщений: 257
29.08.2011, 20:39  [ТС]     Проверка числа на чётность #3
То есть если есть огромный поток чисел, то лучше второй?
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
29.08.2011, 20:42     Проверка числа на чётность #4
Ну, если найдешь компилятор, который генерирует здесь разный код, то наверное.
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 1
29.08.2011, 20:45     Проверка числа на чётность #5
Сообщение было отмечено автором темы, экспертом или модератором как ответ
AvengerAlive, А ты как думаешь?

C++
1
2
3
4
5
6
7
8
9
__declspec(noinline) int f_1(int n)
{
    return n % 2;
}
 
__declspec(noinline) int f_2(int n)
{
    return n & 1;
}
Для первого случая..
Assembler
1
2
3
4
5
6
00FF1000 25 01 00 00 80       and         eax,80000001h  
00FF1005 79 05                jns         f_1+0Ch (0FF100Ch)  
00FF1007 48                   dec         eax  
00FF1008 83 C8 FE             or          eax,0FFFFFFFEh  
00FF100B 40                   inc         eax  
00FF100C C3                   ret
Для второго
Assembler
1
2
00FF1010 83 E0 01             and         eax,1  
00FF1013 C3                   ret
Thinker
Эксперт C++
 Аватар для Thinker
4215 / 2189 / 150
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
29.08.2011, 20:45     Проверка числа на чётность #6
Если есть возможность, работайте с битами, во многих случаях полезно.

Не по теме:

Как у вас с полем дело обстоит?

grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
29.08.2011, 20:49     Проверка числа на чётность #7
ISergey, сравнение не совсем честное, так как результаты этих функций могут различаться, тогда как логическое отрицание даёт одинаковый результат.
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 1
29.08.2011, 21:01     Проверка числа на чётность #8
В любом случаи второй вариант быстрее.
Для такого кода
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
__declspec(noinline) int f_1(int n)
{
    return !(n % 2);
}
 
__declspec(noinline) int f_2(int n)
{
    return !(n & 1);
}
 
int main()
{
    int x; std::cin >> x; // Чтобы компилятор не перестарался с оптимизацией.. 
 
    int a = f_1(x);
    int b = f_2(x);
 
 
    std::cout << a << b; // Это тоже..
    return 0;
}
Получим
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    13: int main()
    14: {
01191030 55                   push        ebp  
01191031 8B EC                mov         ebp,esp  
01191033 51                   push        ecx  
    15:     int x; std::cin >> x;
01191034 8B 0D 48 20 19 01    mov         ecx,dword ptr [__imp_std::cin (1192048h)]  
0119103A 8D 45 FC             lea         eax,[x]  
0119103D 50                   push        eax  
0119103E FF 15 44 20 19 01    call        dword ptr [__imp_std::basic_istream<char,std::char_traits<char> >::operator>> (1192044h)]  
    16: 
    17:     int a = f_1(x);
01191044 8B 4D FC             mov         ecx,dword ptr [x]  
01191047 8B C1                mov         eax,ecx  
01191049 E8 B2 FF FF FF       call        f_1 (1191000h)  
0119104E 8B D0                mov         edx,eax  
    18:     int b = f_2(x);
01191050 8B C1                mov         eax,ecx  
01191052 E8 C9 FF FF FF       call        f_2 (1191020h)  
    19: 
    20: 
    21:     std::cout << a << b;
01191057 8B 0D 50 20 19 01    mov         ecx,dword ptr [__imp_std::cout (1192050h)]  
0119105D 50                   push        eax  
0119105E 52                   push        edx  
0119105F FF 15 4C 20 19 01    call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (119204Ch)]  
01191065 8B C8                mov         ecx,eax  
01191067 FF 15 4C 20 19 01    call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (119204Ch)]  
    22:     return 0;
0119106D 33 C0                xor         eax,eax  
    23: }
0119106F 8B E5                mov         esp,ebp  
01191071 5D                   pop         ebp  
01191072 C3                   ret  
.....
 
     8: __declspec(noinline) int f_2(int n)
     9: {
    10:     return !(n & 1);
01191020 F7 D0                not         eax  
01191022 83 E0 01             and         eax,1  
    11: }
01191025 C3                   ret  
.....
     3: __declspec(noinline) int f_1(int n)
     4: {
     5:     return !(n % 2);
01191000 25 01 00 00 80       and         eax,80000001h  
01191005 79 05                jns         f_1+0Ch (119100Ch)  
01191007 48                   dec         eax  
01191008 83 C8 FE             or          eax,0FFFFFFFEh  
0119100B 40                   inc         eax  
0119100C F7 D8                neg         eax  
0119100E 1B C0                sbb         eax,eax  
01191010 40                   inc         eax  
     6: }
01191011 C3                   ret
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
29.08.2011, 21:05     Проверка числа на чётность #9
ISergey, неужто микрософт?
кстати, а оптимизация была включена?
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 1
29.08.2011, 21:12     Проверка числа на чётность #10
Цитата Сообщение от grizlik78 Посмотреть сообщение
ISergey, неужто микрософт?
Угу
Цитата Сообщение от grizlik78 Посмотреть сообщение
кстати, а оптимизация была включена?
Да. Я ведь спецом добавил int x; std::cin >> x; int a = f_1(x);
что бы компилятор не разошелся..
просто когда так написал
C++
1
int a = f_1(10);
Компилятор не растерялся и выдал мне
Assembler
1
2
3
4
5
6
     3: __declspec(noinline) int f_1(int n)
     4: {
     5:     return !(n % 2);
008C1000 B8 01 00 00 00       mov         eax,1  
     6: }
008C1005 C3                   ret
iama
 Аватар для iama
1249 / 974 / 48
Регистрация: 30.07.2010
Сообщений: 5,297
29.08.2011, 21:13     Проверка числа на чётность #11
grizlik78, битовые операции априори должны выполняться быстрее простой арифметики, раз уж во всех ЭВМ используется двоичная система счисления, разве нет?
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
29.08.2011, 21:23     Проверка числа на чётность #12
Цитата Сообщение от iama Посмотреть сообщение
grizlik78, битовые операции априори должны выполняться быстрее простой арифметики, раз уж во всех ЭВМ используется двоичная система счисления, разве нет?
Ну я же не говорил, что !(a%2) может оказаться быстрее
Просто это тот случай, когда это выражение легко сводится как раз к битовым операциям.

Цитата Сообщение от ISergey Посмотреть сообщение
Угу
Чёрт, я думал, что моё мнение о MSVC не может стать ещё хуже. Я ошибся
Ну хоть в случае unsigned он понимает, что (unsigned(a)%2) и (unsigned(a)&1) это одно и то же?
iama
 Аватар для iama
1249 / 974 / 48
Регистрация: 30.07.2010
Сообщений: 5,297
29.08.2011, 21:55     Проверка числа на чётность #13
Цитата Сообщение от grizlik78 Посмотреть сообщение
Просто это тот случай, когда это выражение легко сводится как раз к битовым операциям.
Выходит, у тебя завышеные ожидания, а у меня - заниженые
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.08.2011, 22:06     Проверка числа на чётность
Еще ссылки по теме:

C++ Определить чётность числа
C++ Проверка чисел на чётность или наоборот, дальнейший вывод
C++ Возведение числа в степень и проверка числа на четность

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
29.08.2011, 22:06     Проверка числа на чётность #14
Да уж. Про ожидания.
Я тут тоже немножко поэкспериментировал c GCC.
Если оптимизацию не включать, то код получается одинаковым. Отбросив лишнее, получается так:
Assembler
1
2
3
4
5
    movl    -4(%rbp), %eax
    andl    $1, %eax
    testl   %eax, %eax
    sete    %al
    movzbl  %al, %eax
Что ж, это вписывается в мои ожидания. В обоих случаях главная операция "and 1"
Однако после включения оптимизации компилятор меня несколько озадачил.
Функция f_1:
Assembler
1
2
3
    xorl    %eax, %eax
    testb   $1, %dil
    sete    %al
Функция f_2
Assembler
1
2
3
    movl    %edi, %eax
    andl    $1, %eax
    xorl    $1, %eax
Шутники

Добавлено через 3 минуты
Да, то была оптимизация по скорости (-O2 или -O3)
При оптимизации по размеру (-O1) код функций снова становится одинаковым
Assembler
1
2
3
    testb   $1, %dil
    sete    %al
    movzbl  %al, %eax
Yandex
Объявления
29.08.2011, 22:06     Проверка числа на чётность
Ответ Создать тему
Опции темы

Текущее время: 15:13. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru