1

I have this code for example:

(a) writeln ('real => ', exp(3*Ln(3)):0:0);  // return 27
(b) writeln ('int => ', int(exp(3*Ln(3))):0:0); // return 26

Is a bug? The function calc 3^3 (exponent using ln and exp function), but conversion from real to int fail; in case (a) return 27, in case (b) return (26), when should be 27 both. As i can solve it? Thanks very much for help.

Ps: Too assign result to integer variable, using trunc, result not change.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
Marcello Impastato
  • 2,263
  • 5
  • 30
  • 52
  • Negative. Subject has been discussed like thousand times before. – Premature Optimization Sep 08 '11 at 18:29
  • @Downvoter, in that case you should vote to close with a link to the duplicate question. – Johan Sep 08 '11 at 20:06
  • possible duplicate of [Why is the result of RoundTo(87.285, -2) => 87.28](http://stackoverflow.com/questions/5191235/why-is-the-result-of-roundto87-285-2-87-28) – Johan Sep 08 '11 at 20:09
  • @Johan, narrowing it Delphi doesnt show whole picture. This "bug" even has been mentioned in mass media: http://www.theregister.co.uk/2006/08/12/floating_point_approximation/ – Premature Optimization Sep 08 '11 at 22:27
  • 1
    FWIW, `Int(X)` does not return an integer, it simply returns the integer value of `X`, i.e. the value of `X` with the fractional part removed. It is equivalent to `Trunc(X)`, except that that does actually return an integer. – Rudy Velthuis Sep 08 '11 at 23:57

5 Answers5

9

No, it is not a bug. Computers simply don't have infinite precision, so the result is not exactly 27, but perhaps 26.999999999 or something. And so, when you int or trunc it, it ends up as 26. Use Round instead.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • It too when real is as: 27.000 ? What sense has round 27.000 to 26.000 ? I don't understand. – Marcello Impastato Sep 08 '11 at 17:24
  • `int` returns the integer part of its argument, that is, its argument rounded towards zero. `trunc` does the same but returns an integer (as the data type). Round rounds to the nearest integer. That's what you want. – Andreas Rejbrand Sep 08 '11 at 17:27
  • but function: exp(3*ln(3)) return 27.000, not 26.9999999 – Marcello Impastato Sep 08 '11 at 17:29
  • 5
    @Marcello: No, it does not. Try `exp(3*ln(3)) = 27.000` yourself, it's `false`. `27.000` is **what is printed on your monitor**, and that's after some procedure has taken the bits of the number as they are stored in memory and created a textual representation from it. – Andreas Rejbrand Sep 08 '11 at 17:30
6

The expression you're printing evaluates to something slightly less than 27 due to the usual floating-point errors. The computer cannot exactly represent the natural logarithm of 3, so any further calculations based on it will have errors, too.

In comments, you claim exp(3*ln(3)) = 27.000, but you've shown no programmatic evidence for that assertion. Your code says exp(3*ln(3)) = 27, which is less precise. It prints that because you explicitly told WriteLn to use less precision. The :0:0 part isn't just decoration. It means that you want to print the result with zero decimal places. When you tell WriteLn to do that, it rounds to that many decimal places. In this case, it rounds up. But when you introduce the call to Int, you truncate the almost-27 value to exactly 26, and then WriteLn trivially rounds that to 26 before printing it.

If you tell WriteLn to display more decimal places, you should see different results. Consult the documentation for Write for details on what the numbers after the colons mean.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
2

Working with floating points doesn't always give a 100% exact result. The reason being is that binary floating points variable can't always represent values exactly. The same thing is true about decimal numbers. If you take 1/3, in a 6 digit precision decimal, would be 0.333333. Then if you take 0.333333 * 3 = 0.999999. Int(0.999999) = 0

Here is some litterature about it...

What Every Computer Scientist Should Know About Floating-Point Arithmetic

Ken Bourassa
  • 6,363
  • 1
  • 19
  • 28
  • I think title is very misleading. Ones who ignored user manual **will** also ignore publication directed toward "scientists". Meanwhile this article contains absolutely mandatory information to be familiarized with **before** approaching the machne. – Premature Optimization Sep 08 '11 at 18:35
1

You should also take a look at Rudy Velthuis' article:

http://rvelthuis.de/articles/articles-floats.html

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
Jørn E. Angeltveit
  • 3,029
  • 3
  • 22
  • 53
0

Not a bug. It is just yet another example of how floating arithmetic works on a computer. Floating point arithmetic is but an approximation of how the real numbers work in mathematics. There is no guarantee, and there can be no such guarantee, that floating point results will be infinitely accurate. In fact, you should expect them to almost always be imprecise to some degree.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • Understood, but as told before, function result 27.000 in first case and 26.000 in second case. And function calc 3*3*3 (in real format) a bit as: 3.000 * 3.000 * 3.000 = 27.000; where is this approssimation from decimal part? But in general if i want calc exactely x^n (n >= 0) as do, without use maths function? need necessary use complex function based on for, if, etc? nothing more simple? I know as solve so, but i try with elegant solution. – Marcello Impastato Sep 08 '11 at 17:28