Math operations precision in PHP 5, PHP 7 - php

When developing calculator in PHP 5+, can programmer get results without thinking on errors of rounding and imprecise representation of decimal numbers?
I mean built-in perfect ways to get, for example, results with given accuracy.
Or each operation like $x = $y * $z + 0.77 must require to develop additional checks in algorithm like rounding (for avoiding errors)?
So errors or imprecision - is up to PHP built-in core or up to developer?
PHP 7 has 64-bit support, what is the improvement on this direction (accuracy of calculations)?

When developing calculator in PHP 5+, can programmer get results without thinking on errors of rounding and imprecise representation of decimal numbers?
Simple answer is No.
Doing arithmetics on decimal basis by using a binary machine like a computer can and will always produce some kind of error.
Many details are explained in this article, it's quite a complex subject.
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Simple example from the decimal world:
The fraction 1/3 can not be expressed as a finite floating point number in decimal notation. Often we try it by writing 0.333333333... but that's not 100% accurate.
Same applies to binary number arithmetics.
[Edit]
If you need a very high degree of precision than you should have a look at phps BC math functions http://php.net/manual/en/ref.bc.php

I don't think there's anything in PHP 7 that will change this. AS #maxhb points out, doing floating point arithmetic is inherently imprecise so you must mind rounding errors.
The 64-bit capability does not fundamentally change this.

Related

PHP Big characteristic double cast issue [duplicate]

It's kind of a common knowledge that (most) floating point numbers are not stored precisely (when IEEE-754 format is used). So one shouldn't do this:
0.3 - 0.2 === 0.1; // very wrong
... as it will result in false, unless some specific arbitrary-precision type/class was used (BigDecimal in Java/Ruby, BCMath in PHP, Math::BigInt/Math::BigFloat in Perl, to name a few) instead.
Yet I wonder why when one tries to print the result of this expression, 0.3 - 0.2, scripting languages (Perl and PHP) give 0.1, but "virtual-machine" ones (Java, JavaScript and Erlang) give something more similar to 0.09999999999999998 instead?
And why is it also inconsistent in Ruby? version 1.8.6 (codepad) gives 0.1, version 1.9.3 (ideone) gives 0.0999...
As for php, output is related to ini settings of precision:
ini_set('precision', 15);
print 0.3 - 0.2; // 0.1
ini_set('precision', 17);
print 0.3 - 0.2; //0.099999999999999978
This may be also cause for other languages
Floating-point numbers are printed differently because printing is done for different purposes, so different choices are made about how to do it.
Printing a floating-point number is a conversion operation: A value encoded in an internal format is converted to a decimal numeral. However, there are choices about the details of the conversion.
(A) If you are doing precise mathematics and want to see the actual value represented by the internal format, then the conversion must be exact: It must produce a decimal numeral that has exactly the same value as the input. (Each floating-point number represents exactly one number. A floating-point number, as defined in the IEEE 754 standard, does not represent an interval.) At times, this may require producing a very large number of digits.
(B) If you do not need the exact value but do need to convert back and forth between the internal format and decimal, then you need to convert it to a decimal numeral precisely (and accurately) enough to distinguish it from any other result. That is, you must produce enough digits that the result is different from what you would get by converting numbers that are adjacent in the internal format. This may require producing a large number of digits, but not so many as to be unmanageable.
(C) If you only want to give the reader a sense of the number, and do not need to produce the exact value in order for your application to function as desired, then you only need to produce as many digits as are needed for your particular application.
Which of these should a conversion do?
Different languages have different defaults because they were developed for different purposes, or because it was not expedient during development to do all the work necessary to produce exact results, or for various other reasons.
(A) requires careful code, and some languages or implementations of them do not provide, or do not guarantee to provide, this behavior.
(B) is required by Java, I believe. However, as we saw in a recent question, it can have some unexpected behavior. (65.12 is printed as “65.12” because the latter has enough digits to distinguish it from nearby values, but 65.12-2 is printed as “63.120000000000005” because there is another floating-point value between it and 63.12, so you need the extra digits to distinguish them.)
(C) is what some languages use by default. It is, in essence, wrong, since no single value for how many digits to print can be suitable for all applications. Indeed, we have seen over decades that it fosters continuing misconceptions about floating-point, largely by concealing the true values involved. It is, however, easy to implement, and hence is attractive to some implementors. Ideally, a language should by default print the correct value of a floating-point number. If fewer digits are to be displayed, the number of digits should be selected only by the application implementor, hopefully including consideration of the appropriate number of digits to produce the desire results.
Worse, some languages, in addition to not displaying the actual value or enough digits to distinguish it, do not even guarantee that the digits produced are correct in some sense (such as being the value you would get by rounding the exact value to the number of digits shown). When programming in an implementation that does not provide a guarantee about this behavior, you are not doing engineering.
PHP automatically rounds the number to an arbitrary precision.
Floating-point numbers in general aren't accurate (as you noted), and you should use the language-specific round() function if you need a comparison with only a few decimal places. Otherwise, take the absolute value of the equation, and test they are within a given range.
PHP Example from php.net:
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
if(abs($a - $b) < $epsilon) {
echo "true";
}
As for the Ruby issue, they appear to be using different versions. Codepad uses 1.8.6, While Ideaone uses 1.9.3, but it's more likely related to a config somewhere.
If we want this property
every two different float has a different printed representation
Or an even stronger one useful for REPL
printed representation shall be re-interpreted unchanged
Then I see 3 solutions for printing a float/double with base 2 internal representation into base 10
print the EXACT representation.
print enough decimal digits (with proper rounding)
print the shortest decimal representation that can be reinterpreted unchanged
Since in base two, the float number is an_integer * 2^an_exponent, its base 10 exact representation has a finite number of digits.
Unfortunately, this can result in very long strings...
For example 1.0e-10 is represented exactly as 1.0000000000000000364321973154977415791655470655996396089904010295867919921875e-10
Solution 2 is easy, you use printf with 17 digits for IEEE-754 double...
Drawback: it's not exact, nor the shortest! If you enter 0.1, you get
0.100000000000000006
Solution 3 is the best one for REPL languages, if you enter 0.1, it prints 0.1
Unfortunately it is not found in standard libraries (a shame).
At least, Scheme, Python and recent Squeak/Pharo Smalltalk do it right, I think Java too.
As for Javascript, base2 is being used internally for calculations.
> 0.2 + 0.4
0.6000000000000001
For that, Javascript can only deliver even numbers, if the resulting base2 number is not periodic.
0.6 is 0.10011 10011 10011 10011 ... in base2 (periodic), whereas 0.5 is not and therefore correctly printed.

why pow(3^47) gives wrong answer? [duplicate]

This question already has answers here:
Unexpected results when working with very big integers on interpreted languages
(36 answers)
Working with large numbers in PHP
(8 answers)
Closed 9 years ago.
using php, this code echo sprintf('%.9F',pow(3,47)); outputs 26588814358957501972480.000000000
where as other sites like this gives 3^47 = 26588814358957503287787. Is there any bug with PHP? How to resolve it?
btw, i'd like to know what is the maximum digit php can handle for calculation using pow,sprintf,fmod. Is it 300 digits?
You need to use an external program or a PHP extension (library).
I've just tested it with BC Math and GMP using the bcpow()/gmp_pow() functions and it works perfectly:
<?php
// both output 26588814358957503287787
echo bcpow('3', '47');
echo gmp_strval( gmp_pow('3', '47') );
The PHP.net documentation has a nice section about that topic:
Floating point precision
Floating point numbers have limited precision. Although it depends on
the system, PHP typically uses the IEEE 754 double precision format,
which will give a maximum relative error due to rounding in the order
of 1.11e-16. Non elementary arithmetic operations may give larger
errors, and, of course, error propagation must be considered when
several operations are compounded.
Additionally, rational numbers that are exactly representable as
floating point numbers in base 10, like 0.1 or 0.7, do not have an
exact representation as floating point numbers in base 2, which is
used internally, no matter the size of the mantissa. Hence, they
cannot be converted into their internal binary counterparts without a
small loss of precision. This can lead to confusing results: for
example, floor((0.1+0.7)*10) will usually return 7 instead of the
expected 8, since the internal representation will be something like
7.9999999999999991118....
So never trust floating number results to the last digit, and do not
compare floating point numbers directly for equality. If higher
precision is necessary, the arbitrary precision math functions and gmp
functions are available.
For a "simple" explanation, see the » floating point guide that's also
titled "Why don’t my numbers add up?"
— http://php.net/manual/en/language.types.float.php
Note that the php.ini configuration value 'precision' can also modify the precision when converting from floats to strings.
bcpow() (a function of the BCMath Arbitrary Precision Mathematics library) can be used in this case.
echo bcpow('3', '47'); //as mentioned in ComFreek's answer
//outputs 26588814358957503287787
The reason why pow isn't work here is because pow() uses float, and there's a size limitation for float.
See this excerpt from the PHP Manual:
The size of a float is platform-dependent, although a maximum of ~1.8e308 with a precision of roughly 14 decimal digits is a common value (the 64 bit IEEE format)
In other words, the maximum possible size may vary -- i.e. (may be different for 32-bit, and 64-bit systems).
Hope that answers your question!

Why are floating point numbers printed so differently?

It's kind of a common knowledge that (most) floating point numbers are not stored precisely (when IEEE-754 format is used). So one shouldn't do this:
0.3 - 0.2 === 0.1; // very wrong
... as it will result in false, unless some specific arbitrary-precision type/class was used (BigDecimal in Java/Ruby, BCMath in PHP, Math::BigInt/Math::BigFloat in Perl, to name a few) instead.
Yet I wonder why when one tries to print the result of this expression, 0.3 - 0.2, scripting languages (Perl and PHP) give 0.1, but "virtual-machine" ones (Java, JavaScript and Erlang) give something more similar to 0.09999999999999998 instead?
And why is it also inconsistent in Ruby? version 1.8.6 (codepad) gives 0.1, version 1.9.3 (ideone) gives 0.0999...
As for php, output is related to ini settings of precision:
ini_set('precision', 15);
print 0.3 - 0.2; // 0.1
ini_set('precision', 17);
print 0.3 - 0.2; //0.099999999999999978
This may be also cause for other languages
Floating-point numbers are printed differently because printing is done for different purposes, so different choices are made about how to do it.
Printing a floating-point number is a conversion operation: A value encoded in an internal format is converted to a decimal numeral. However, there are choices about the details of the conversion.
(A) If you are doing precise mathematics and want to see the actual value represented by the internal format, then the conversion must be exact: It must produce a decimal numeral that has exactly the same value as the input. (Each floating-point number represents exactly one number. A floating-point number, as defined in the IEEE 754 standard, does not represent an interval.) At times, this may require producing a very large number of digits.
(B) If you do not need the exact value but do need to convert back and forth between the internal format and decimal, then you need to convert it to a decimal numeral precisely (and accurately) enough to distinguish it from any other result. That is, you must produce enough digits that the result is different from what you would get by converting numbers that are adjacent in the internal format. This may require producing a large number of digits, but not so many as to be unmanageable.
(C) If you only want to give the reader a sense of the number, and do not need to produce the exact value in order for your application to function as desired, then you only need to produce as many digits as are needed for your particular application.
Which of these should a conversion do?
Different languages have different defaults because they were developed for different purposes, or because it was not expedient during development to do all the work necessary to produce exact results, or for various other reasons.
(A) requires careful code, and some languages or implementations of them do not provide, or do not guarantee to provide, this behavior.
(B) is required by Java, I believe. However, as we saw in a recent question, it can have some unexpected behavior. (65.12 is printed as “65.12” because the latter has enough digits to distinguish it from nearby values, but 65.12-2 is printed as “63.120000000000005” because there is another floating-point value between it and 63.12, so you need the extra digits to distinguish them.)
(C) is what some languages use by default. It is, in essence, wrong, since no single value for how many digits to print can be suitable for all applications. Indeed, we have seen over decades that it fosters continuing misconceptions about floating-point, largely by concealing the true values involved. It is, however, easy to implement, and hence is attractive to some implementors. Ideally, a language should by default print the correct value of a floating-point number. If fewer digits are to be displayed, the number of digits should be selected only by the application implementor, hopefully including consideration of the appropriate number of digits to produce the desire results.
Worse, some languages, in addition to not displaying the actual value or enough digits to distinguish it, do not even guarantee that the digits produced are correct in some sense (such as being the value you would get by rounding the exact value to the number of digits shown). When programming in an implementation that does not provide a guarantee about this behavior, you are not doing engineering.
PHP automatically rounds the number to an arbitrary precision.
Floating-point numbers in general aren't accurate (as you noted), and you should use the language-specific round() function if you need a comparison with only a few decimal places. Otherwise, take the absolute value of the equation, and test they are within a given range.
PHP Example from php.net:
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
if(abs($a - $b) < $epsilon) {
echo "true";
}
As for the Ruby issue, they appear to be using different versions. Codepad uses 1.8.6, While Ideaone uses 1.9.3, but it's more likely related to a config somewhere.
If we want this property
every two different float has a different printed representation
Or an even stronger one useful for REPL
printed representation shall be re-interpreted unchanged
Then I see 3 solutions for printing a float/double with base 2 internal representation into base 10
print the EXACT representation.
print enough decimal digits (with proper rounding)
print the shortest decimal representation that can be reinterpreted unchanged
Since in base two, the float number is an_integer * 2^an_exponent, its base 10 exact representation has a finite number of digits.
Unfortunately, this can result in very long strings...
For example 1.0e-10 is represented exactly as 1.0000000000000000364321973154977415791655470655996396089904010295867919921875e-10
Solution 2 is easy, you use printf with 17 digits for IEEE-754 double...
Drawback: it's not exact, nor the shortest! If you enter 0.1, you get
0.100000000000000006
Solution 3 is the best one for REPL languages, if you enter 0.1, it prints 0.1
Unfortunately it is not found in standard libraries (a shame).
At least, Scheme, Python and recent Squeak/Pharo Smalltalk do it right, I think Java too.
As for Javascript, base2 is being used internally for calculations.
> 0.2 + 0.4
0.6000000000000001
For that, Javascript can only deliver even numbers, if the resulting base2 number is not periodic.
0.6 is 0.10011 10011 10011 10011 ... in base2 (periodic), whereas 0.5 is not and therefore correctly printed.

why 0.1+0.2-0.3= 5.5511151231258E-17 in php [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
The accuracy of PHP float calculate
when i executed the code below in eclipse , the result was not 0 but 5.5511151231258E-17
$a = 0.1+0.2-0.3;
echo $a;
could someone tell me why?
This is because floating point numbers have limited precision.
You can find more information about this trait on this page in the PHP manual.
Floating point numbers have limited precision. Although it depends on
the system, PHP typically uses the IEEE 754 double precision format,
which will give a maximum relative error due to rounding in the order
of 1.11e-16. Non elementary arithmetic operations may give larger
errors, and, of course, error progragation must be considered when
several operations are compounded.
Additionally, rational numbers that are exactly representable as
floating point numbers in base 10, like 0.1 or 0.7, do not have an
exact representation as floating point numbers in base 2, which is
used internally, no matter the size of the mantissa. Hence, they
cannot be converted into their internal binary counterparts without a
small loss of precision. This can lead to confusing results: for
example, floor((0.1+0.7)*10) will usually return 7 instead of the
expected 8, since the internal representation will be something like
7.9999999999999991118....
So never trust floating number results to the last digit, and never
compare floating point numbers for equality. If higher precision is
necessary, the arbitrary precision math functions and gmp functions
are available.
Please note that this is not a trait specific to PHP; it is just the way floating point numbers work.
You're running into PHP's floating point precision issues. All languages have them, you've just found PHP's.
This is not PHP specific, as others have mentioned. However, you can avoid limited floating point precision by using round():
<?php
$a = 0.1+0.3-0.2;
echo round($a, 2);
?>
Of course you will need to know the number of digits beforehand.
It's because computers can't accurately represent floating point numbers. This isn't specific to PHP.
See here for details.

0.699 x 100 = 69.89999999999999? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Why does 99.99 / 100 = 0.9998999999999999
Dealing with accuracy problems in floating-point numbers
I've seen this issue in php and javascript. I have this number: float 0.699
if I do this:
0.699 x 100 = 69.89999999999999
why?
edit
round(0.699 x 10, 2): float 69.90000000000001
Floating point arithmetic is not exact.
See Floating point on Wikipedia for a deeper discussion of the problem.
This is what has helped me in the past. It has a lot to do with how things are represented in binary. Basically long story short in binary there isn't an exact number for all real numbers of large numbers.
The link below will describe that in more detail for you.
What Every Computer Scientist Should Know About Floating-Point Arithmetic
This will happen in any language. Floats, like everything else on a computer, are stored as binary. The number 0.699, while representable exactly in decimal, is probably a repeating decimal in binary, so it can't be stored to exact precision.
Check out the wikipedia entry for how floats are stored, and why this happens.
Javascript numbers are floating point.
Take a look at The complete javascript number reference. Excerpt:
All numbers in Javascript are 64bit (8
bytes) floating point numbers which
yields an effective range of 5e-324
(negative) to 1.7976931348623157e+308
(positive) at the time this article
was written (this may eventually
change to 128 bits in the future as 64
bit processors become commonplace and
the ECMA standards evolve).
Integers are considered reliable
(numbers without a period or exponent
notation) to 15 digits (9e15) 1.
Floating point numbers are considered
only as reliable as possible and no
more! This is an especially important
concept to understand for currency
manipulation as 0.06 + 0.01 resolves
to 0.06999999999999999 instead of
0.07.
Take a look at Floating Point, specifically the section on IEEE 754 and representable numbers.
This behavior can be reproduced in many programming languages, including C++ and Assembly. The reason is floating point format using by FPU. You can read details here:
http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_14/CH14-1.html#HEADING1-19
General rule: never expect exact result of floating-point operations. Never compare two floating point numbers, use interval, for example: instead of testing f1 == f2, use f1 > (f2 -e) and f1 < ( f2 + e ), e is some small value.

Categories