From: "Uri Guttman" <u...@stemsystems.com>
sorry to say but you still don't get it. automatically rounding numbers
is not higher level NOR correct. there is NO correct way to handle
floating numbers like that. none. nada. it is a very well known issue in
ALL programming languages that support floats. some choose convenience
solutions which may work some of the time but will screw up worse other
times. the correct solution for money has always been to use integers
for the smallest amount (e.g. cents). this will always be correct in all
languanges.
To be sincere, I doubt that those languages/programs that use convenience
methods fail sometimes. I made some tests with very well known databases,
and they seem to work and I don't think a database management system is made
so bad:
Oracle:
SQL> select 0.079 - 0.085 from dual;
0.079-0.085
-----------
-.006
PostgreSQL:
postgres=# select 0.079 - 0.085;
?column?
----------
-0.006
MySQL:
mysql> select 0.079 - 0.085;
+---------------+
| 0.079 - 0.085 |
+---------------+
| -0.006 |
But SQLite, exactly like Perl, doesn't do this:
sqlite> select 0.079 - 0.085;
-0.00600000000000001
Do you say that these databases make mistakes and I shouldn't use decimal
and float type columns?
>> If you want more accurate results, consider using bignum or bigrat
>> (see `perldoc bignum` and `perldoc bigrat`).
OR> That's what I needed! I found that I can use Math::BigFloat or
OR> sprintf(), but it is ugly to manually create an object for every float
OR> used, or round each number, but it seems that bignum it is the way to
OR> go, and it offers more features.
and that is much slower than integers for money. much much slower.
you can choose what you want but the key point is that you make a
rational choice based on the facts, not based on some emotional reaction
to which appears more correct. this is the lesson you should learn here
more than anything else. programming is a set of logical decisions and
your code is the record of the choices you made.
Well, I don't remember to have read a big warning to not make float
calculations in perl at all because the results are not correct, or to not
store floats in a database for the same reason. I knew about the errors that
might be encountered when using floats, but I thought that this refers to
the fact that the computer can't calculate the "correct" value for
operations like 1/3, and I knew that in cases like this it is very normal to
expect losing some decimals.
The result is that I have floats in databases and the perl code for doing
calculations with them should be very ugly.
Speaking about the accuracy of the program, I am interested in no more than
8 digits after the decimal point, and doing something like the following
should be very enough:
my $x = 0.079;
my $y = 0.085;
$x *= 100000000;
$y *= 100000000;
my $result = ($x - $y) / 100000000;
So I don't need to use the numbers as objects as bignum offers, but I need
to be able to do this automaticly, without making 3 math operations instead
of a single one in my program because the code would look much clean.
You are right, using bignum would be a few hundreads times slower than doing
the
calculation directly and using the method above would be just a few times
slower, and if perl would do this internally it could be even faster.
Anyway, I've seen that PHP does the following program twice as fast as perl:
<?php
for($aa=1; $aa<=50000000; $aa++) {
$x = 0.079 - 0.085;
}
?>
but it also gives a correct result.
If I want a correct result with perl, I need to do more calculations and it
would be even much slower so any solution available in perl would have
disadvantages.
A few years ago I made some Fibonacci test comparison between perl and PHP
and perl was faster, but now PHP is faster when doing those tests.
I know that Java does some internal optimizations when doing that kind of
calculations, like the Memoize module does for perl, but when using that
kind of optimization the speed is very big and well, the speed of PHP is
just a little big, so I doubt it uses optimizations. It seems to just do the
calculations faster.
Anyway, the results matter, and finally the same calculation is done faster
in PHP and in a cleaner mode and the result is the expected one, although we
all consider PHP a bad language.
Please tell me if I am wrong and if there is a better method I didn't think
about.
Thank you.
Octavian
--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/