Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> промежуточная переменная изменяет результат 
V
    Опции темы
borisbn
Дата 11.9.2012, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Здравствуйте.
Есть код
Код
    double x = 1e-6;
    double y = 1e6;
    double z = x * y;
    if ( z >= 1.0 )
       cout << "zzz" << endl;
    if ( x * y >= 1.0 )
       cout << "xxx yyy" << endl;
    cout << "z = " << std::setprecision( 42 ) << z << endl;
    cout << "x*y = " << std::setprecision( 42 ) << x * y << endl;

http://liveworkspace.org/code/56a6afbdb322...e351b2af54057a7

выводит 
Цитата
zzz
z = 1
x*y = 1


Вопрос. Почему почему выводит "zzz" и не  выводит "xxx yyy" ?
Спасибо.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
bsa
Дата 11.9.2012, 15:35 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



потому что x*y может быть равен 0,999999999999999999999999999999999999999999999999999  smile 
Поэтому все операции с действительными числами нужно производить через эпсилон.
PM   Вверх
math64
Дата 11.9.2012, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



bsa, это не объясняет результата.
Не помогает 
Код

if ( (double)(x * y) >= 1.0 ) cout << "x*y" << endl; // Не печатается - компилятор ингорирует приведение типа

добавляем 
Код

long double ld = x*y;
if (ld >= 1.0) cout << "ld" << endl; // Не печатается

1. Получается: все промежуточные вычисления промежуточные ведутся в long double
2. По стандарту они должны идти в double - поэтому приведение к (double) игнорируется как бесполезная операция.
3. При присваивании переменной компилятор вынужден сделать приведение типа.
И вот Вам результат ...

PM   Вверх
borisbn
Дата 11.9.2012, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(bsa @  11.9.2012,  15:35 Найти цитируемый пост)
все операции с действительными числами нужно производить через эпсилон.

это я знаю. вопрос более теоретический.
Если 
Цитата(bsa @  11.9.2012,  15:35 Найти цитируемый пост)
x*y может быть равен 0,999999999999999999999999999999999999999999999999999

то почему при присвоении этого к z что-то меняется ?

Добавлено через 2 минуты и 41 секунду
Цитата(math64 @  11.9.2012,  16:22 Найти цитируемый пост)
все промежуточные вычисления промежуточные ведутся в long double

судя по этому - http://liveworkspace.org/code/f22c5b620f53...feb5fcb6adb8c81 - в double


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
math64
Дата 11.9.2012, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Цитата(borisbn @  11.9.2012,  16:25 Найти цитируемый пост)
судя по этому - http://liveworkspace.org/code/f22c5b620f53...feb5fcb6adb8c81 - в double 

Я же писал
Цитата(math64 @  11.9.2012,  16:22 Найти цитируемый пост)
2. По стандарту они должны идти в double - поэтому приведение к (double) игнорируется как бесполезная операция.

По той же причине sizeof(x*y) равен sizeof(double).
PM   Вверх
borisbn
Дата 11.9.2012, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



ещё один момент: в 2008-й студии печатает 
Цитата
zzz
xxx yyy
z = 1
x*y = 1

 smile

Добавлено через 3 минуты и 52 секунды
math64, я тут подумал... да.... похоже Вы правы. Господа, вам не кажется, что это - глюк компилятора ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Dem_max
Дата 11.9.2012, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 4
Всего: 39



Никаких глюков, два вариант могут существовать во вселенной


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
math64
Дата 11.9.2012, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Код

if ((float)(x*y) >= 1.0) cout << "float x*y" << endl; // печатается

т.е. (float) не игнорируется.

Ещё результат может зависеть от оптимизации.
PM   Вверх
borisbn
Дата 11.9.2012, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



У меня нет возможности посмотреть ассемблерный код, который генерит GCC. Если кто-нибудь не поленится и выложит сюда - буду благодарен. 


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
math64
Дата 11.9.2012, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



gcc 3.4.2 mingw
Код

#include <iostream>
#include <iomanip>
using namespace std;
int main() {
    double x = 1e-6;
    double y = 1e6;
    double z = x * y;
    if ( z >= 1.0 )
       cout << "zzz" << endl;
    long double ld = x*y;
    if (ld >= 1.0) cout << "ld" << endl; // Не печатается
    if ( x * y >= 1.0 )
       cout << "xxx yyy" << endl;
    if ( (float)(x * y) >= 1.0 )
       cout << "fxy" << endl;
    cout << "z = " << std::setprecision( 42 ) << z << endl;
    cout << "x*y = " << std::setprecision( 42 ) << x * y << endl;
}

Код

    .file    "xy.cpp"
    .text
    .align 2
    .def    __ZSt17__verify_groupingPKcjRKSs;    .scl    3;    .type    32;    .endef
__ZSt17__verify_groupingPKcjRKSs:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $40, %esp
    movl    16(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZNKSs4sizeEv
    decl    %eax
    movl    %eax, -4(%ebp)
    movl    12(%ebp), %eax
    decl    %eax
    movl    %eax, -12(%ebp)
    leal    -12(%ebp), %eax
    movl    %eax, 4(%esp)
    leal    -4(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZSt3minIjERKT_S2_S2_
    movl    (%eax), %eax
    movl    %eax, -8(%ebp)
    movl    -4(%ebp), %eax
    movl    %eax, -16(%ebp)
    movb    $1, -17(%ebp)
    movl    $0, -24(%ebp)
L2:
    movl    -24(%ebp), %eax
    cmpl    -8(%ebp), %eax
    jae    L5
    cmpb    $0, -17(%ebp)
    je    L5
    movl    -16(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    16(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZNKSsixEj
    movl    %eax, %ecx
    movl    8(%ebp), %eax
    movl    -24(%ebp), %edx
    addl    %eax, %edx
    movzbl    (%ecx), %eax
    cmpb    (%edx), %al
    sete    %al
    movb    %al, -17(%ebp)
    leal    -16(%ebp), %eax
    decl    (%eax)
    leal    -24(%ebp), %eax
    incl    (%eax)
    jmp    L2
L5:
    cmpl    $0, -16(%ebp)
    je    L6
    cmpb    $0, -17(%ebp)
    je    L6
    movl    -16(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    16(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZNKSsixEj
    movl    %eax, %ecx
    movl    8(%ebp), %eax
    movl    -8(%ebp), %edx
    addl    %eax, %edx
    movzbl    (%ecx), %eax
    cmpb    (%edx), %al
    sete    %al
    movb    %al, -17(%ebp)
    leal    -16(%ebp), %eax
    decl    (%eax)
    jmp    L5
L6:
    movl    $0, 4(%esp)
    movl    16(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZNKSsixEj
    movl    %eax, %ecx
    movl    8(%ebp), %eax
    movl    -8(%ebp), %edx
    addl    %eax, %edx
    movzbl    (%ecx), %eax
    cmpb    (%edx), %al
    jg    L8
    movzbl    -17(%ebp), %eax
    andl    $1, %eax
    movb    %al, -25(%ebp)
    jmp    L9
L8:
    movb    $0, -25(%ebp)
L9:
    movzbl    -25(%ebp), %eax
    movb    %al, -17(%ebp)
    movzbl    -17(%ebp), %eax
    leave
    ret
.lcomm __ZSt8__ioinit,16
    .def    ___main;    .scl    2;    .type    32;    .endef
    .section .rdata,"dr"
LC3:
    .ascii "zzz\0"
LC5:
    .ascii "ld\0"
LC6:
    .ascii "xxx yyy\0"
LC8:
    .ascii "fxy\0"
LC9:
    .ascii "z = \0"
LC10:
    .ascii "x*y = \0"
    .align 8
LC0:
    .long    -1598689907
    .long    1051772663
    .align 8
LC1:
    .long    0
    .long    1093567616
    .text
    .align 2
.globl _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $104, %esp
    andl    $-16, %esp
    movl    $0, %eax
    addl    $15, %eax
    addl    $15, %eax
    shrl    $4, %eax
    sall    $4, %eax
    movl    %eax, -76(%ebp)
    movl    -76(%ebp), %eax
    call    __alloca
    call    ___main
    fldl    LC0
    fstpl    -16(%ebp)
    fldl    LC1
    fstpl    -24(%ebp)
    fldl    -16(%ebp)
    fmull    -24(%ebp)
    fstpl    -32(%ebp)
    fldl    -32(%ebp)
    fld1
    fxch    %st(1)
    fucompp
    fnstsw    %ax
    sahf
    jae    L12
    jmp    L11
L12:
    movl    $LC3, 4(%esp)
    movl    $__ZSt4cout, (%esp)
    call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
    movl    %eax, (%esp)
    call    __ZNSolsEPFRSoS_E
L11:
    fldl    -16(%ebp)
    fmull    -24(%ebp)
    fstpt    -56(%ebp)
    fldt    -56(%ebp)
    fld1
    fxch    %st(1)
    fucompp
    fnstsw    %ax
    sahf
    jae    L14
    jmp    L13
L14:
    movl    $LC5, 4(%esp)
    movl    $__ZSt4cout, (%esp)
    call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
    movl    %eax, (%esp)
    call    __ZNSolsEPFRSoS_E
L13:
    fldl    -16(%ebp)
    fmull    -24(%ebp)
    fld1
    fxch    %st(1)
    fucompp
    fnstsw    %ax
    sahf
    jae    L16
    jmp    L15
L16:
    movl    $LC6, 4(%esp)
    movl    $__ZSt4cout, (%esp)
    call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
    movl    %eax, (%esp)
    call    __ZNSolsEPFRSoS_E
L15:
    fldl    -16(%ebp)
    fmull    -24(%ebp)
    fstps    -60(%ebp)
    flds    -60(%ebp)
    fld1
    fxch    %st(1)
    fucompp
    fnstsw    %ax
    sahf
    jae    L18
    jmp    L17
L18:
    movl    $LC8, 4(%esp)
    movl    $__ZSt4cout, (%esp)
    call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
    movl    %eax, (%esp)
    call    __ZNSolsEPFRSoS_E
L17:
    movl    $42, (%esp)
    call    __ZSt12setprecisioni
    movl    %eax, -64(%ebp)
    movl    $LC9, 4(%esp)
    movl    $__ZSt4cout, (%esp)
    call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    %eax, %edx
    movl    -64(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    %edx, (%esp)
    call    __ZStlsIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_St13_Setprecision
    fldl    -32(%ebp)
    fstpl    4(%esp)
    movl    %eax, (%esp)
    call    __ZNSolsEd
    movl    $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
    movl    %eax, (%esp)
    call    __ZNSolsEPFRSoS_E
    movl    $42, (%esp)
    call    __ZSt12setprecisioni
    movl    %eax, -68(%ebp)
    movl    $LC10, 4(%esp)
    movl    $__ZSt4cout, (%esp)
    call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    %eax, %edx
    movl    -68(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    %edx, (%esp)
    call    __ZStlsIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_St13_Setprecision
    fldl    -16(%ebp)
    fmull    -24(%ebp)
    fstpl    4(%esp)
    movl    %eax, (%esp)
    call    __ZNSolsEd
    movl    $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
    movl    %eax, (%esp)
    call    __ZNSolsEPFRSoS_E
    movl    $0, %eax
    leave
    ret
    .section    .text$_ZSt12setprecisioni,"x"
    .linkonce discard
    .align 2
.globl __ZSt12setprecisioni
    .def    __ZSt12setprecisioni;    .scl    2;    .type    32;    .endef
__ZSt12setprecisioni:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, -4(%ebp)
    movl    -4(%ebp), %eax
    leave
    ret
    .section    .text$_ZSt3minIjERKT_S2_S2_,"x"
    .linkonce discard
    .align 2
.globl __ZSt3minIjERKT_S2_S2_
    .def    __ZSt3minIjERKT_S2_S2_;    .scl    2;    .type    32;    .endef
__ZSt3minIjERKT_S2_S2_:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    12(%ebp), %eax
    movl    8(%ebp), %edx
    movl    (%eax), %eax
    cmpl    (%edx), %eax
    jae    L21
    movl    12(%ebp), %eax
    movl    %eax, -4(%ebp)
    jmp    L20
L21:
    movl    8(%ebp), %eax
    movl    %eax, -4(%ebp)
L20:
    movl    -4(%ebp), %eax
    leave
    ret
    .text
    .align 2
    .def    __Z41__static_initialization_and_destruction_0ii;    .scl    3;    .type    32;    .endef
__Z41__static_initialization_and_destruction_0ii:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    cmpl    $65535, 12(%ebp)
    jne    L23
    cmpl    $1, 8(%ebp)
    jne    L23
    movl    $__ZSt8__ioinit, (%esp)
    call    __ZNSt8ios_base4InitC1Ev
L23:
    cmpl    $65535, 12(%ebp)
    jne    L22
    cmpl    $0, 8(%ebp)
    jne    L22
    movl    $__ZSt8__ioinit, (%esp)
    call    __ZNSt8ios_base4InitD1Ev
L22:
    leave
    ret
    .align 2
    .def    __GLOBAL__I_main;    .scl    3;    .type    32;    .endef
__GLOBAL__I_main:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    $65535, 4(%esp)
    movl    $1, (%esp)
    call    __Z41__static_initialization_and_destruction_0ii
    leave
    ret
    .section    .ctors,"w"
    .align 4
    .long    __GLOBAL__I_main
    .text
    .align 2
    .def    __GLOBAL__D_main;    .scl    3;    .type    32;    .endef
__GLOBAL__D_main:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    $65535, 4(%esp)
    movl    $0, (%esp)
    call    __Z41__static_initialization_and_destruction_0ii
    leave
    ret
    .section    .dtors,"w"
    .align 4
    .long    __GLOBAL__D_main
    .def    __ZNSt8ios_base4InitD1Ev;    .scl    3;    .type    32;    .endef
    .def    __ZNSolsEd;    .scl    3;    .type    32;    .endef
    .def    __ZStlsIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_St13_Setprecision;    .scl    3;    .type    32;    .endef
    .def    __ZNSolsEPFRSoS_E;    .scl    3;    .type    32;    .endef
    .def    __ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_;    .scl    3;    .type    32;    .endef
    .def    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc;    .scl    3;    .type    32;    .endef
    .def    __ZNSt8ios_base4InitC1Ev;    .scl    3;    .type    32;    .endef
    .def    __ZNKSsixEj;    .scl    3;    .type    32;    .endef
    .def    __ZNKSs4sizeEv;    .scl    3;    .type    32;    .endef
    .def    __ZSt3minIjERKT_S2_S2_;    .scl    3;    .type    32;    .endef

PM   Вверх
borisbn
Дата 11.9.2012, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



math64, спасибо.

Цитата(borisbn @  11.9.2012,  18:00 Найти цитируемый пост)
У меня нет возможности посмотреть ассемблерный код, который генерит GCC.

это я, пожалуй, погорячился... ничего не понятно.
все четыре сравнения кажутся одинаковыми

Цитата(math64 @  11.9.2012,  18:08 Найти цитируемый пост)
if ( z >= 1.0 )

=
Цитата(math64 @  11.9.2012,  18:08 Найти цитируемый пост)
    fldl    LC0
    fstpl    -16(%ebp)
    fldl    LC1
    fstpl    -24(%ebp)            // <--- кажется разница только в этом
    fldl    -16(%ebp)
    fmull    -24(%ebp)
    fstpl    -32(%ebp)
    fldl    -32(%ebp)
    fld1
    fxch    %st(1)
    fucompp


Цитата(math64 @  11.9.2012,  18:08 Найти цитируемый пост)
if (ld >= 1.0)

=
Цитата(math64 @  11.9.2012,  18:08 Найти цитируемый пост)
    fldl    -16(%ebp)
    fmull    -24(%ebp)
    fstpt    -56(%ebp)            // <--- кажется разница только в этом
    fldt    -56(%ebp)
    fld1
    fxch    %st(1)
    fucompp


Цитата(math64 @  11.9.2012,  18:08 Найти цитируемый пост)
if ( x * y >= 1.0 )

=
Цитата(math64 @  11.9.2012,  18:08 Найти цитируемый пост)
    fldl    -16(%ebp)
    fmull    -24(%ebp)
    fld1
    fxch    %st(1)
    fucompp


Цитата(math64 @  11.9.2012,  18:08 Найти цитируемый пост)
if ( (float)(x * y) >= 1.0 )

=
Цитата(math64 @  11.9.2012,  18:08 Найти цитируемый пост)
    fldl    -16(%ebp)
    fmull    -24(%ebp)
    fstps    -60(%ebp)            // <--- кажется разница только в этом
    flds    -60(%ebp)
    fld1
    fxch    %st(1)
    fucompp


Добавлено через 1 минуту и 18 секунд
Цитата(borisbn @  11.9.2012,  21:17 Найти цитируемый пост)
это я, пожалуй, погорячился... ничего не понятно.

я имел в виду: кто-нибудь может прокомментировать приведённый ассемблер ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
math64
Дата 12.9.2012, 07:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Используются разные ассемблерные команды.
Код

z = x * y;
if ( z >= 1.0 )

Код

    fstpl    -32(%ebp) ; результат вычислений из стека сопроцессора в z с округлением (cуффикс *l - 8 байтовая переменная)
    fldl    -32(%ebp) ; загружаем z в стек сопроцессора

Код

ld = x * y;
if (ld >= 1.0)

Код

    fstpt    -56(%ebp) ; результат вычислений из стека сопроцессора в ld без округления (*t - 10 байтовая переменная)
    fldt    -56(%ebp) ; загружаем ld в стек сопроцессора

Код
if ( x * y >= 1.0 )

нет сохранения результата умножения, за умножением сразу идёт сравнение
Код
if ( (float)(x * y) >= 1.0 )

Код

    fstps    -60(%ebp) ; результат сохраняется с округлением во временную переменную (*s - 4 байтовая переменная)
    flds    -60(%ebp)



Это сообщение отредактировал(а) math64 - 12.9.2012, 07:26
PM   Вверх
xvr
Дата 12.9.2012, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Кстати, в 64х битной версии gcc печатает и zzz и xxx yyy
И при включении уровня оптимизаций -O3 (для 32х битной) тоже печатает оба

У меня на gcc (64 бита на Linux, версия 4.1.2) код немного получился другой, но суть та же

Вариант с промежуточной переменной:
Код

        fldl    -32(%ebp)
        fmull   -24(%ebp)   ; Умножение
        fstpl   -16(%ebp)   ; Выгрузка в память
        fldl    -16(%ebp)   ; Загрузка обратно

         ; Собственно сравнение
        fld1
        fxch    %st(1)
        fucompp


Без промежуточной переменной:
Код

        fldl    -32(%ebp)
        fmull   -24(%ebp)

         ; Собственно сравнение
        fld1
        fxch    %st(1)
        fucompp
Ничего никуда не выгружается - используется сразу со стека FPU. Сам FPU все операции делает над 80ти битным представлением, что явно точнее, чем 64 бита типа double (в который и была выгрузка в 1м случае)


PM MAIL   Вверх
borisbn
Дата 12.9.2012, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(xvr @  12.9.2012,  16:44 Найти цитируемый пост)
в 64х битной версии gcc печатает и zzz и xxx yyy

жесть... всегда был уверен (не знаю почему), что 64 и 32 бита отличаются лишь работой с памятью, размером указателей и т.п., а операции с числами (int не берём) абсолютно одинаковые. Что ж... ошибался


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
math64
Дата 12.9.2012, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Но в данном случае при уменьшении точности получаем более точный результат, о чем говорили в теме
исползование double вместо float
http://forum.vingrad.ru/forum/topic-355758.html

Добавлено через 14 минут и 2 секунды
Цитата(borisbn @  12.9.2012,  21:24 Найти цитируемый пост)
жесть... всегда был уверен (не знаю почему), что 64 и 32 бита отличаются лишь работой с памятью, размером указателей и т.п., а операции с числами (int не берём) абсолютно одинаковые. Что ж... ошибался 

Если бы компилятор работал бы по стандарту - так и было бы.
Т.е. после каждой операции нужно было бы выгружать результат во временную переменную и загружать в FPU снова.
Но это потеря во времени, и как правило, потеря точности (данный пример, когда при округлении получаем более точный результат - исключение), поэтому проводится оптимизация.
Пользователь от этого обычно не страдает.

Вот в начале 80-х была другая ситуация.
Машина - PDP-11/70, 16 разрядная. Компилятор Fortran-77.
Нужно 32 разрядное целое.
Пишем INTEGER*4 I
Компилятор съедает, но I - 16 разрядная.
Спрашиваем: Почему игнорируется *4?
Ответ: потому что по стандарту фортрана INTEGER и INTEGER*4 - одно и то же.
В: А почему тогда INTEGER 16 разрядный?
О: Потому что процессор 16 разрядный
Приходится использовать REAL

PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1044 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.