Floating point error?
The following C code:
float f = 5.15002; double d = 5.15002; if (d + FLT_EPSILON f) puts("huh?"); Where 'FLT_EPSILON' is defined as the minimum number whereby 1.0 + FLT_EPSILON != 1.0, causes the string "huh!" to be printed out on my system (Pentium III) I have included the relevant assembly code below. Now is this a bug in the intel chip, or allowable because FLT_EPSILON makes no promises when added to numbers greater than 1.0? It doesn't happen when 'd' is another float, so presumably it has something to do with double-precision/single-precision conversions too. Curious... Dylan 8: float f = 5.15002; 00401028 C7 45 FC F7 CC A4 40 mov dword ptr [ebp-4],40A4CCF7h 9: double d = 5.15002; 0040102F C7 45 F4 D2 FB C6 D7 mov dword ptr [ebp-0Ch],0D7C6FBD2h 00401036 C7 45 F8 9E 99 14 40 mov dword ptr [ebp-8],4014999Eh 10: if (d + FLT_EPSILON f) 0040103D DD 45 F4 fld qword ptr [ebp-0Ch] 00401040 DC 05 28 60 42 00 fadd qword ptr [__real@8@3fe88000000000000000 (00426028)] 00401046 D9 45 FC fld dword ptr [ebp-4] 00401049 DE D9 fcompp 0040104B DF E0 fnstsw ax 0040104D F6 C4 41 test ah,41h 00401050 75 0D jne main+4Fh (0040105f) 11: puts("huh?"); 00401052 68 1C 60 42 00 push offset string "huh?" (0042601c) 00401057 E8 34 00 00 00 call puts (00401090) 0040105C 83 C4 04 add esp,4 12: return 0; 0040105F 33 C0 xor eax,eax |
float f = 5.15002;
double d = 5.15002; if (d + FLT_EPSILON f) puts("huh?"); Where 'FLT_EPSILON' is defined as the minimum number whereby 1.0 + FLT_EPSILON != 1.0, causes the string "huh!" to be printed out on my system (Pentium III) I have included the relevant assembly code below. Now is this a bug in the intel chip, or allowable because FLT_EPSILON makes no promises when added to numbers greater than 1.0? It's allowable because FLT_EPSILON makes no promises when added to numbers greater than 1.0. Since this is an IEEE implementation with FLT_RADIX of 2, I'd expect it to work if (d + 4.0*FLT_EPSILON f) puts("huh?"); for values of f where f = 4.0 and f 8.0 . It doesn't happen when 'd' is another float, so presumably it has something to do with double-precision/single-precision conversions too. Curious... There is no exact representation of most non-integer decimal numbers in binary floating point. This is the case for 5.15002 above. You can't get an exact representation without an INFINITE number of bits, but the more bits you use, the closer you'll get. Expect double - float to lose accuracy. And don't think about "decimal digits". 0.1 in binary is an infinite repeating fraction. Gordon L. Burditt |
Jack Klein wrote:
On 15 Jul 2003 19:25:24 -0700, (Dylan Nicholson) wrote in comp.lang.asm.x86: The following C code: float f = 5.15002; double d = 5.15002; if (d + FLT_EPSILON f) puts("huh?"); Where 'FLT_EPSILON' is defined as the minimum number whereby 1.0 + FLT_EPSILON != 1.0, causes the string "huh!" to be printed out on my system (Pentium III) I have included the relevant assembly code below. Now is this a bug in the intel chip, or allowable because FLT_EPSILON makes no promises when added to numbers greater than 1.0? It doesn't happen when 'd' is another float, so presumably it has something to do with double-precision/single-precision conversions too. Curious... Dylan [snip] You're misunderstanding the meaning of FLT_EPSILON. If you want to check the minimum representable difference between the float representation of 10.0 and the next higher float value, you need to use FLT_EPSILON * 10. If you were checking a value around 100, you would need to use FLT_EPSILON * 100. "close enough for government work" More accurately, FLT_EPSILON times the largest integer power of FLT_RADIX which is less than the number to be compared. 4*FLT_EPSILON in the case above. Not a good idea to redefine a constant defined by Standard C, as the OP implies he is doing. -- Tim Prince |
All times are GMT +1. The time now is 08:43 AM. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
HardwareBanter.com