【发布时间】:2014-03-28 14:35:39
【问题描述】:
我想得到一个准确/准确的答案,为什么下面的代码会打印出不同的结果:
#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;
}
我认为这可能取决于编译器,我的是 gcc (GCC mingw Windows7) 4.8.1 和 gcc (Debian 4.7.2-5) 4.7.2。
非常感谢!
更新!
我生成了带有和不带有 -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
使用 -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
【问题讨论】:
-
这不可能是真的...您能否将
a和b打印为整数并检查它们是否为9 和10? This website 也声称使用相同的编译器,它会为两者打印1,就像它应该的那样。 -
为 gcc 4.8.2 打印 1/1
-
由于浮点数学不精确(并且编译器以不同的精度存储临时结果),我希望这样的行为。但我在 gcc (x64) 上也得到 1/1。
-
您可以通过直接打印两个除法结果以高精度获得更多信息,而不是通过比较它们。我的猜测是,对于您的编译器,带有文字的编译器在编译时进行评估,带有变量的编译器在运行时进行评估,结果具有不同的精度。
-
@ThoAppelsin:我花了半天时间才发现这对我的程序造成了问题。我不相信它,但它是真的。 4.8.1 编译器的更多信息:它来自 Windows7 上的 MinGW(我不知道是否重要)。
标签: c gcc floating-point comparison