I'd like to get an exact/precise answer why the following code prints different results:
#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;
}
I think this might be compiler dependent, mine is gcc (GCC mingw Windows7) 4.8.1 and gcc (Debian 4.7.2-5) 4.7.2.
Thank you very much!
UPDATE!
I generated the assembly codes with and without the -std=c99 option, this should be helping to understand what is happening here.
Without -std=c99 (this gives the result 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
With -std=c99 (this gives the result 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
In C, floating point math is allowed to run in higher precision than the code indicates.
Especially the compile time math (2nd line) may run as a long double
C11dr §5.2.4.2.2 9 "Except for assignment and cast (which remove all extra range and precision), the values yielded by operators with floating operands and values subject to the usual arithmetic conversions and of floating constants are evaluated to a format whose range and precision may be greater than required by the type.
See @Patricia Shanahan above.
[Edit]
Check the FP evaluation mode, if defined
#include <float.h>
printf("%d\n", FLT_EVAL_METHOD);
C11dr §5.2.4.2.2 9 (cont.) The use of evaluation formats is characterized by the implementation-defined value of FLT_EVAL_METHOD
.
-1
indeterminable;
0
evaluate all operations and constants just to the range and precision of the
type;
1
evaluate operations and constants of type float and double to the
range and precision of the double type, evaluate long double operations and constants to the range and precision of the long double type;
2
evaluate all operations and constants to the range and precision of the
long double type.
All other negative values for FLT_EVAL_METHOD characterize implementation-defined behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With