Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Math bug in Borland compilers.

Status
Not open for further replies.

Ferran

Programmer
May 11, 2000
7
0
0
ES
Hello,<br><br>Some months ago I found a bug (I think) in all Borland compilers I tried.<br><br>Consider this function :<br><br>int Bug()<br>{<br>double a;<br>int c;<br><br>a=75.0;<br>c=a*(3000.0/2500.0);<br><br>return c;<br>}<br><br>You can expect than this function returns 90, but it returns 89!<br>If you replace &quot;c=a*(3000.0/2500.0);&quot; for &quot;c=a*((float)3000.0/(float)2500.0);&quot; or for &quot;c=a*3000.0/2500.0;&quot; then it returns 90 correctly. Also if you declare c as float works well too. <br><br>I have tried this in TC 3.0, Borland C++ 5.02 and Builder 4. With Microsoft Visual C++ 6.0 doesn't happen. I had reported this to Borland on Feb. 25th and haven't received response yet! :-(<br><br>Can anyone try this in Builder 5?
 
This again proves the value of separating the sheep and the goats. Mixing types 'should normally be safe' as the compilers will jump through hoops to accomodate our coding 'sins', coverting types, etc.&nbsp;&nbsp;:)&nbsp;&nbsp;This is an interesting one, though most of these 'error animals' do an implicit float or double to int conversion to hilight the 'fault'. MS had similar problems a few years back with Excel calculations (which one assumes was written in MS C++), giving divide errors on integer values!
 
I had seen a similar effect. I got different results running a program in the IDE and as standalone. I think that is a problem of the run time Library. <p>hnd<br><a href=mailto:hasso55@yahoo.com>hasso55@yahoo.com</a><br><a href= > </a><br>
 
Instead of getting 90 , you are getting 89 . it is because it you look at the storage method . The double stores it as 80.999999 something depending upon the system.<br>I have a code , just run it. And find the answer . <br>#include &lt;stdio.h&gt;<br>int main() {<br>&nbsp;&nbsp;&nbsp;&nbsp;float a = 3.7;<br>&nbsp;&nbsp;&nbsp;&nbsp;if (a == 3.7)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;A is 3.7\n&quot;);<br>&nbsp;&nbsp;&nbsp;&nbsp;else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Not 3.7 &quot;);<br>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br>}<br><br>Thanx<br>Siddhartha Singh<br><A HREF="mailto:ssingh@aztecsoft.com">ssingh@aztecsoft.com</A> <p>Siddhartha Singh<br><a href=mailto:siddhu_singh@hotmail.com>siddhu_singh@hotmail.com</a><br><a href=siddhu.freehosting.net> </a><br>
 
Is more than a storage method problem. The following example return 90.<br><br>int Bug()<br>{<br>double a,b;<br>int c;<br><br>a=75.0;<br>b=a*(3000.0/2500.0);<br>c=b;<br><br>return c;<br>}<br><br>Th only diference is the usage of 'b'. <p>Ferran Casarramona<br><a href=mailto: > </a><br><a href= > </a><br>
 
then it could be a bug. But amazingly, when b is assigned to an int c. The value changes to 90. Is it??? Did you check thru breakpoints that when the value is assigned to b then it has 89&nbsp;&nbsp;and when b is assigned to c the value of c is 90. If this is happening then we must inform Borland.<br>But this is just amazing.<br><br> <p>Siddhartha Singh<br><a href=mailto:siddhu_singh@hotmail.com>siddhu_singh@hotmail.com</a><br><a href=siddhu.freehosting.net> </a><br>
 
No, 'b' is assigned 90. I have inspected the assembler code and I think I have found the solution:<br><br>&nbsp;Borland and Microsoft compilers generate the same code :<br><br>c=a*(3000.0/2500.0);<br>0040144B DD 05 28 51 41 00&nbsp;&nbsp;&nbsp;fld&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;qword ptr[00415128]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; constant = 1.2 (note than in binary have not an&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; exact representation)<br>00401451 DC 4D 80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmul&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;qword ptr [a]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; Multiply<br>00401454 E8 57 0B 00 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_ftol (00401fb0)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; Conversion to int<br>00401459 89 85 74 FF FF FF&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dword ptr [c],eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; assigning to int.<br><br>but after multiply, Borland gives a result of 89.99999999999... and Microsoft give 90.0000000000. The reason for this is than Borland works with more precision, (the Precision Control (PC) bits of the FPU &quot;Control Word&quot; is marked to use 64 bits precision by Borland programs and 53 bit precision by Microsoft programs), so the result is not rounded to 90 after the multiply operation. (I had found this technical details about i486 processors and compatibles at <A HREF=" TARGET="_new"> )<br><br>I still don't understand why when assigning to a double the result is rounded to 90, but not if is assigned directly to a int. I suppose than the FPU work internally with more precision than &quot;double&quot; type and no rounded operations are made.<br><br>Now the question is : Is best use high precision inside FPU than in memory as Borland does? Or is better use the same precision to get the same results if we use memory variables or FPU registers? <p>Ferran Casarramona<br><a href=mailto: > </a><br><a href= > </a><br>
 
Ferran,<br><br>&nbsp;&nbsp;&nbsp;&nbsp;It will depend on what you are looking for. If you are just going to round to the nearest integer, then less decimal precision is best. If you need to carry the decimal out then the reverse is best. It is up to the programmer to make these decisions and the programmer should be aware of how to squeeze the best out of the compiler.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;As a side note, I notice in the June issue of <b>C/C++ Users Journal</b> that there is an article by Pete Becker on <i>Floating Point Basics</i>. I haven't read the article yet so I can't say if it applies here but it <u>may</u> explain some things.<br><br> <p>James P. Cottingham<br><a href=mailto: > </a><br><a href= Veneer Co., Inc.</a><br>All opinions are mine alone and do not necessarily reflect those of my employer.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top