Bar*_*jak 5 c floating-point comparison gcc
我想得到一个确切/准确的答案,为什么下面的代码打印出不同的结果:
#include "stdio.h"
int main(void)
{
int a = 9;
int b = 10;
printf("%d\n", (double)a / (double)b == 0.9); /* prints 0 */
printf("%d\n", (double)9 / (double)10 == 0.9); /* prints 1 */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我认为这可能是编译器依赖的,我的是gcc(GCC mingw Windows7)4.8.1和gcc(Debian 4.7.2-5)4.7.2.
非常感谢你!
UPDATE!
我使用和不使用-std = c99选项生成汇编代码,这应该有助于理解这里发生的事情.
没有-std = c99(这给出了结果0/1):
.file "a.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d\n"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB11:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
movl $1, 4(%esp)
movl $.LC0, (%esp)
call printf
movl $1, 4(%esp)
movl $.LC0, (%esp)
call printf
xorl %eax, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE11:
.size main, .-main
.ident "GCC: (Debian 4.7.2-5) 4.7.2"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
使用-std = c99(这会得到结果1/1):
.file "a.c"
.section .rodata
.LC1:
.string "%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
movl $9, 28(%esp)
movl $10, 24(%esp)
fildl 28(%esp)
fildl 24(%esp)
fdivrp %st, %st(1)
movl $1, %edx
fldt .LC0
fucomp %st(1)
fnstsw %ax
sahf
jp .L5
fldt .LC0
fucompp
fnstsw %ax
sahf
je .L2
jmp .L3
.L5:
fstp %st(0)
.L3:
movl $0, %edx
.L2:
movzbl %dl, %eax
movl %eax, 4(%esp)
movl $.LC1, (%esp)
call printf
movl $1, 4(%esp)
movl $.LC1, (%esp)
call printf
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.section .rodata
.align 16
.LC0:
.long 1717986918
.long -429496730
.long 16382
.ident "GCC: (Debian 4.7.2-5) 4.7.2"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
在 C 中,浮点数学允许以比代码指示的更高的精度运行。
\n特别是编译时数学(第二行)可以作为long double
\n\n\nC11dr \xc2\xa75.2.4.2.2 9 “除了赋值和转换(删除所有额外的范围和精度)之外,具有浮动操作数的运算符和经过通常算术转换的值以及浮动常量所产生的值被评估为其范围和精度可能大于类型所需的格式。
\n
请参阅上面的@Patricia Shanahan。
\n\n[编辑]
\n\n检查 FP 评估模式(如果已定义)
\n\n#include <float.h>\nprintf("%d\\n", FLT_EVAL_METHOD);\nRun Code Online (Sandbox Code Playgroud)\n\nC11dr \xc2\xa75.2.4.2.2 9(续) 评估格式的使用以 的实现定义值为特征FLT_EVAL_METHOD。
-1无法确定的;
0仅根据类型的范围和精度评估所有操作和常量;
1将 float 和 double 类型的运算和常量计算为 double 类型的范围和精度,将 long double 运算和常量计算为 long double 类型的范围和精度;
2将所有运算和常量评估为 long double 类型的范围和精度。
FLT_EVAL_METHOD 的所有其他负值都表示实现定义的行为。
\n| 归档时间: |
|
| 查看次数: |
306 次 |
| 最近记录: |