eacj@batcomputer.tn.cornell.edu (Julian Vrieslander) (08/08/88)
I hope someone can explain this one for me. The following code fragment is a simplified version of a routine that was giving me unexpected results. The results below were obtained in LightspeedC version 3.0, running under System 6.0: double d; long m,n; m = 126.0; /* m becomes 126 */ d = 12.6 * 10.0; /* d becomes 126 */ n = d; /* n becomes 125 !! */ I cannot understand why n gets "rounded down" to 125. Am I missing something subtle about C syntax or IEEE type conversions, or is this a bug in SANE or LSC? The variable values shown in the comments were verified with the LSC debugger and with my own debugging dialog. If I use the debugger to force a value of 126.0 into d before the last line is executed, then n gets the correct result. What's happening here? -- Julian Vrieslander "Don't rush me... you'll get a rotten miracle." Neurobiology & Behavior, W250 Mudd Hall, Cornell University, Ithaca NY 14853 UUCP: {cmcl2,decvax,rochester,uw-beaver,ihnp4}!cornell!batcomputer!eacj INTERNET: eacj@tcgould.tn.cornell.edu BITNET: eacj@CRNLTHRY
drc@claris.UUCP (Dennis Cohen) (08/08/88)
In article <5813@batcomputer.tn.cornell.edu> eacj@tcgould.tn.cornell.edu (Julian Vrieslander) writes: > double d; > long m,n; > > m = 126.0; /* m becomes 126 */ > d = 12.6 * 10.0; /* d becomes 126 */ > n = d; /* n becomes 125 !! */ > >I cannot understand why n gets "rounded down" to 125. Am I missing >something subtle about C syntax or IEEE type conversions, or is this a bug >in SANE or LSC? The variable values shown in the comments were verified >with the LSC debugger and with my own debugging dialog. If I use the >debugger to force a value of 126.0 into d before the last line is >executed, then n gets the correct result. What's happening here? Well, d is a double that is being assigned the product of two floats, the first of which does not have an exact binary representation. Because of this, d will be 125.999(something). When you now assign d to n (an integer type) it will truncate (not round) to make the assignment. This is not very nice, but it is "correct" behavior (so far as C, Pascal, and most other languages are concerned). Dennis Cohen Claris Corp. ------------ Disclaimer: Any opinions expressed above are _MINE_!
anson@spray.CalComp.COM (Ed Anson) (08/08/88)
In article <5813@batcomputer.tn.cornell.edu> eacj@tcgould.tn.cornell.edu (Julian Vrieslander) writes: > > m = 126.0; /* m becomes 126 */ > d = 12.6 * 10.0; /* d becomes 126 */ > n = d; /* n becomes 125 !! */ > >I cannot understand why n gets "rounded down" to 125. Because of the differences between binary and decimal notation, the value 12.6 cannot be represented exactly in floating point format. My guess is that 12.6 gets converted to something just a hair lower than 12.6, which will always give the result described. When converting from floating point to integer, I generally round the value, rather than simply truncate. That approach saves a lot of grief. -- ===================================================================== Ed Anson, Calcomp Display Products Division, Hudson NH 03051 (603) 885-8712, anson@elrond.CalComp.COM
set@teddy.UUCP (Sean E. Trowbridge) (08/08/88)
In article <5813@batcomputer.tn.cornell.edu> eacj@tcgould.tn.cornell.edu (Julian Vrieslander) writes: > > double d; > long m,n; > > m = 126.0; /* m becomes 126 */ > d = 12.6 * 10.0; /* d becomes 126 */ > n = d; /* n becomes 125 !! */ > >I cannot understand why n gets "rounded down" to 125. >Julian Vrieslander "Don't rush me... you'll get a rotten miracle." Floating point calculations are not always exact, since numbers are converted from decimal to binary and back. Since converting from a float to an int simply truncates the fractional part, I would imagine that 12.6 * 10.0 gives you 125.9999999, and assigning that value to an int (long) gives you 125. Sean Trowbridge
pollock@usfvax2.EDU (Wayne Pollock) (08/23/88)
In article <5813@batcomputer.tn.cornell.edu> (Julian Vrieslander) writes: > > double d; > long m,n; > > m = 126.0; /* m becomes 126 */ > d = 12.6 * 10.0; /* d becomes 126 */ > n = d; /* n becomes 125 !! */ > >I cannot understand why n gets "rounded down" to 125. This is just a result of floating point roundoff error. To make things work right when assigning a float or double to an int or long, always add a small amount like this: n = d + 0.00001; if you want to truncate accurately, or use: n = d + 0.5; or some library routine if you want to round the number. Assuming the default conversions will always work perfectly is just asking for trouble. Wayne Pollock (The MAD Scientist) pollock@usfvax2.usf.edu Usenet: ...!{uflorida, codas}!usfvax2!pollock GEnie: W.POLLOCK
palmer@tybalt.caltech.edu (David Palmer) (08/23/88)
In article <1120@usfvax2.EDU> pollock@usfvax2.usf.edu.UUCP (Wayne Pollock) writes: > .... >, or use: > > n = d + 0.5; > >or some library routine if you want to round the number. Assuming the >default conversions will always work perfectly is just asking for >trouble. Use a library routine. n=d + 0.5 does not properly round d if d < 0 (or more precisely, d < -0.5). if d=-1.0, for instance, d+0.5 = -0.5 which is truncated to 0 when it is assigned to an integer variable. As long as you have thoroughly memorized K&R's white book, you should have no problem. David Palmer palmer@tybalt.caltech.edu ...rutgers!cit-vax!tybalt.caltech.edu!palmer "Flowers -- Just say NO!!" - Mighty Mouse