Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Целочисленные типы в выражениях


Автор: S.A.G. 27.3.2008, 09:28
Значит так, имеем код, он ВЫПОЛНЯЕТ нужную задачу - начиная с 13 по 19 место заполняет массив числом 10000.0..:
Код

        for (i = 13; i < 20; i++)
        {
            int j = ceil((float)(i / 2));
                if (((float)i / 2) == j)
                    continue;
            WholeFuncCoeff[i] = 10000;
        }

Но почему вот такой код НЕ приносит желаемый результат:
Код

        for (i = 13; i < 20; i++)
        {
            int j = ceil((float)(i / 2));
                if ((/*(float)*/i / 2) == j)
                    continue;
            WholeFuncCoeff[i] = 10000;
        }

Или может следует даже вот так записать, чтобы сравнивать плавающие типы с одинаковой точностью(?):
Код

        for (i = 13; i < 20; i++)
        {
            float j = ceil((float)(i / 2));
                if (((float)i / 2) == j)
                    continue;
            WholeFuncCoeff[i] = 10000;
        }

Я всегда знал, что если:
Код

int i = 5;
i = i / 2;

, то i будет равно 2. Но если имеем выражение (i / 2), разве оно не должно быть типа double = 2.5 по стандарту??? А то пришлось явно приводить i к float перед делением!

Автор: korian 27.3.2008, 09:49
если целое делиться на целое - результат целое
решение: надо один из типов перевести в float
Код

        for (i = 13; i < 20; i++)
        {
            int j = ceil(i / 2.); //или (i / 2.f)
                if ((i / 2.) == j)
                    continue;
            WholeFuncCoeff[i] = 10000;
        }


Автор: S.A.G. 27.3.2008, 09:55
Цитата(korian @  27.3.2008,  09:49 Найти цитируемый пост)
если целое делиться на целое - результат целое

Я думал, что это проявляется только при присвоении переменной целого типа значения типа не целого. Но в выражениях!..

Добавлено через 10 минут и 2 секунды
Но тогда можно не заморачиваться и просто записать проверку на парность:
Код

if ((double)(i / 2) == (i / 2.))
    continue;

Тут double сравнивается с double? Числовые плавающие константы в С, я знаю, имеют тип double, а в С++ тоже так?

Автор: mes 27.3.2008, 11:07
Цитата(S.A.G. @  27.3.2008,  09:55 Найти цитируемый пост)
((double)(i / 2) == 


если нужен дробный тип дели так  (i/2.0)

Автор: Earnest 27.3.2008, 11:35
Что-то я не пойму - это ты так четность проверяешь?

Автор: S.A.G. 27.3.2008, 12:20
Вот этим(?):
Код

if ((double)(i / 2) == (i / 2.))
    continue;

Ну да.

Добавлено через 32 секунды
Цитата(S.A.G. @  27.3.2008,  09:55 Найти цитируемый пост)
Тут double сравнивается с double?

?

Автор: Sleepless 27.3.2008, 12:40
Цитата(Earnest @  27.3.2008,  11:35 Найти цитируемый пост)
Что-то я не пойму - это ты так четность проверяешь? 


Цитата(S.A.G. @  27.3.2008,  12:20 Найти цитируемый пост)
Ну да.

http://forum.vingrad.ru/forum/topic-202920.html

Автор: inside_pointer 27.3.2008, 13:02
Цитата("S.A.G.")

Но если имеем выражение (i / 2), разве оно не должно быть типа double = 2.5 по стандарту??? А то пришлось явно приводить i к float перед делением!

Чтобы i само привелось к double надо поставить 2.0, результат тоже будет double, и j даже если оно целое, в операции сравнения с этим результатом тоже должно преобразоваться в double.
А при делении i / 2 если i целое, то 2 к double не приводится, и результат соответственно тоже не получается как double, а идёт как int, у которого нет дробной части.

Автор: S.A.G. 27.3.2008, 17:12
Sleepless, мой метод тоже подходит. smile

Автор: vinter 27.3.2008, 17:17
Цитата(S.A.G. @  27.3.2008,  18:12 Найти цитируемый пост)
Sleepless, мой метод тоже подходит

угу, только если так писать то в конце концов разгневанный человек ,смотрящий твой код, придет к тебе ночью с холодным оружием..

Автор: Sleepless 27.3.2008, 17:20
Цитата(S.A.G. @  27.3.2008,  17:12 Найти цитируемый пост)
Sleepless, мой метод тоже подходит

В общем случае, Ваш метод может не работать из-за ограниченной точности представления вещественных чисел.

Автор: S.A.G. 27.3.2008, 17:56
Sleepless, ага, может не совпасть на 0.00000001 или около того. Вобщем, забыл я такой простой оператор - целочисленное деление. smile

Автор: Earnest 27.3.2008, 19:08
Цитата(S.A.G. @  27.3.2008,  18:12 Найти цитируемый пост)
Sleepless, мой метод тоже подходит.

Да, для шифрования кода. smile 
S.A.G., настоящие C-программеры проверяют четность так: i&1
 smile 
Хотя, конечно, нынче компиляторы из  i%2 делают то же самое...

Автор: S.A.G. 27.3.2008, 19:14
Earnest, i&1?

Автор: baldina 27.3.2008, 20:08
S.A.G., i&1 - проверка младшего бита. вспомни, что числа у нас в двоичной системе, каждый разряд кратен степени двойки. потому вот...

Автор: Sleepless 28.3.2008, 11:25
Цитата(Earnest @  27.3.2008,  19:08 Найти цитируемый пост)
Хотя, конечно, нынче компиляторы из  i%2 делают то же самое...

ИМХО, идеальный компилятор должен привести оба варианта к сдвигу вправо и анализу полученного бита... Кстати, VS 2005 для двух вариантов сгенерирует разный код, причем сдвига не будет ни в одном из них.

Автор: bsa 28.3.2008, 13:57
Цитата(Sleepless @ 28.3.2008,  11:25)
ИМХО, идеальный компилятор должен привести оба варианта к сдвигу вправо и анализу полученного бита...

Это откуда такая уверенность? Ты думаешь, скорость выполнения сдвига выше, чем у операции AND?

Автор: Sleepless 28.3.2008, 14:14
Цитата(bsa @  28.3.2008,  13:57 Найти цитируемый пост)
Это откуда такая уверенность?

100% уверенности нет, т.к. обе операции регистровые. Только "И" требует 2 операнда... Ладно, пороюсь на досуге в Интеловской локументации

Автор: baldina 28.3.2008, 14:19
Sleepless, был удивлен, проверил. Все-таки оно одинаковый код генерит...

Автор: Sleepless 28.3.2008, 14:21
Цитата(baldina @  28.3.2008,  14:19 Найти цитируемый пост)
Sleepless, был удивлен, проверил. Все-таки оно одинаковый код генерит... 

Ты про VS2005? Приведи С++ код, листинг и укажи настройки компилятора - сравню с моими

Автор: baldina 28.3.2008, 14:29
Если честно, на 2005 не проверял. Проверял на 2003 и 2008. Они генерят абсолютно одинаковый код. Потому думаю, что и 2005 не выделяется.
Код

  std::cout << (abc%2) << std::endl;
mov         eax,dword ptr [__imp_std::endl (40200Ch)] 
mov         ecx,dword ptr [abc (403018h)] 
and         ecx,1 
push        eax  
push        ecx  
mov         ecx,dword ptr [__imp_std::cout (402008h)] 
call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402010h)] 
mov         ecx,eax 
call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402014h)] 
  std::cout << (abc&1) << std::endl;
mov         edx,dword ptr [__imp_std::endl (40200Ch)] 
mov         eax,dword ptr [abc (403018h)] 
mov         ecx,dword ptr [__imp_std::cout (402008h)] 
push        edx  
and         eax,1 
push        eax  
call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402010h)] 
mov         ecx,eax 
call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402014h)] 


Добавлено через 3 минуты и 40 секунд
unsigned abc;

если тип знаковый, код, понятно, будет разным...

Автор: Sleepless 28.3.2008, 14:54
Цитата(Sleepless @  28.3.2008,  11:25 Найти цитируемый пост)
Кстати, VS 2005 для двух вариантов сгенерирует разный код, причем сдвига не будет ни в одном из них. 

Цитата(baldina @  28.3.2008,  14:29 Найти цитируемый пост)
Они генерят абсолютно одинаковый код

Хм... Ты прав... Я ошибся :( Интересно, куда я смотрел? 

Может кто-нибудь привести код, сгенерированный не MS-компилятором?

Автор: korian 28.3.2008, 14:58
Цитата(Sleepless @  28.3.2008,  13:54 Найти цитируемый пост)
Хм... Ты прав... Я ошибся :( Интересно, куда я смотрел? 

я вообще не понимаю о чем тут спорить...
тогда уж надо проверить все компиляторы, причем на каждом проверить все платформы (x86, x486... Core2Duo, потом AMD т.д.) и после этого можно будет только составить статистику, какой код генерится чаще.

Автор: Любитель 30.3.2008, 00:03
Я за энд smile

Автор: Mayk 30.3.2008, 10:29
Цитата(Sleepless @  28.3.2008,  18:54 Найти цитируемый пост)

Может кто-нибудь привести код, сгенерированный не MS-компилятором? 

Код

int imod2( int x ){
    return x  % 2;
}

int umod2( unsigned x ){
    return x  % 2;
}


gcc (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2):
Код

imod2:
.LFB2:
    movl    %edi, %edx
    shrl    $31, %edx
    leal    (%rdi,%rdx), %eax
    andl    $1, %eax
    subl    %edx, %eax
    ret
.LFE2:
    .size    imod2, .-imod2
    .p2align 4,,15
.globl umod2
    .type    umod2, @function
umod2:
.LFB3:
    andl    $1, %edi
    movl    %edi, %eax
    ret



q3lcc. версию умалчивает. как он связан с ку3 не помню.
Код

imod2:
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
movl %esp,%ebp
movl 20(%ebp),%eax
movl $2,%ecx
cdq
idivl %ecx
movl %edx,%eax
.LC1:
movl %ebp,%esp
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
.Lf2:
.size imod2,.Lf2-imod2
.globl umod2
.align 16
.type umod2,@function
umod2:
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
movl %esp,%ebp
movl 20(%ebp),%edi
andl $1,%edi
movl %edi,%eax
.LC3:
movl %ebp,%esp
popl %edi
popl %esi
popl %ebx
popl %ebp
ret


tcc: Information: Version: 4.0, Machine: linux-*-80x86, Release: TenDRA-4.1.2.
Код

imod2:
.set .Ldisp0, 0           
 movl 4+.Ldisp0(%esp),%eax
 andl $1,%eax
 ret
.align 4
.size imod2, .-imod2
.text
.type umod2,@function
.globl umod2
.align 16
umod2:
.set .Ldisp2, 0           
 movl 4+.Ldisp2(%esp),%eax
 andl $1,%eax
 ret


искать другие компиляторы в лом.

Автор: Любитель 30.3.2008, 10:47
Код
movl 4+.Ldisp0(%esp),%eax andl $1,%eax

и
Код
movl 4+.Ldisp0(%esp),%eax andl $1,%eax

хде отличие? smile 


Автор: bsa 30.3.2008, 11:28
ICC:
Код
umod2:
# parameter 1: %edi
..B1.1:                         # Preds ..B1.0
..___tag_value_umod2.1:                                         #5.24
        andl      $1, %edi                                      #6.14
        movl      %edi, %eax                                    #6.14
        ret                                                     #6.14
#........
imod2:
# parameter 1: %edi
..B2.1:                         # Preds ..B2.0
..___tag_value_imod2.9:                                         #1.19
        movl      %edi, %eax                                    #2.14
        andl      $-2147483647, %eax                            #2.14
        jge       ..B2.4        # Prob 50%                      #2.14
                                # LOE rbx rbp r12 r13 r14 r15 eax
..B2.5:                         # Preds ..B2.1
        decl      %eax                                          #2.14
        orl       $-2, %eax                                     #2.14
        incl      %eax                                          #2.14
                                # LOE rbx rbp r12 r13 r14 r15 eax
..B2.4:                         # Preds ..B2.1 ..B2.5
        ret                                                     #2.14

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)