PHP expression output [duplicate] - php

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
I found somewhere in book
echo (int) ((0.1 + 0.7) * 10);
output is : 7
echo ((0.1 + 0.7) * 10);
output : 8
why both out are different ? I think answer should be 8

When you write
echo ((0.1 + 0.7) * 10);
the result of this simple arithmetic
expression is stored internally as 7.999999 instead of 8.
Now when the value is converted to int,
echo (int) ((0.1 + 0.7) * 10); // 7.999999 when typecasted to int becomes 7
PHP simply truncates away the fractional part, resulting in a rather
significant error (12.5%, to be exact).

It's because float point at this scenario does not fit to memory and is truncated when converting to integer.
Read about that in PHP manual about float
Warning
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.

Please check http://php.net/manual/en/language.types.integer.php and find this
Warning : Never cast an unknown fraction to integer, as this can sometimes lead to unexpected results.
<?php
echo (int) ( (0.1+0.7) * 10 ); // echoes 7!
?>
See also the warning about float precision.

Related

(int) does not type-convert multiplication result correctly [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
If I use (int) to convert a product between a float type variable and an integer, the result is not what I expect it to. Please see my code.
The expectation is that the result is 4090270, not 4090269
(int)(4090270.0) works correctly
$amount = 40902.70; // Same for 40902.20
$amount= (int)($amount*100);
echo $amount; /// Output : 4090269
Never cast an unknown fraction to integer, as this can sometimes lead to unexpected results.
According to PHP documentation
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....
See this reference.
Try like this.
$amount = 40902.70; // Same for 40902.20
$amounts= intval(strval($amount*100));;
echo $amounts;
Note: intval and int converts doubles to integers by truncating the fractional component of the number.
For more info check : reference
$test1 = intVal(1999);
$amount = 19.99 * 100;
$test2 = intVal($amount);
$test3 = intVal("$amount");
echo $test1 . "<br />\n";
echo $test2 . "<br />\n";
echo $test3 . "<br />\n";
expected output:
1999
1999
1999
actual output
1999
1998
1999
Appears to be a floating point issue, but the number 1999 is the only number that I was able to get to do this. 19.99 is the price of many things, and for our purpose we must pass it as 1999 instead of 19.99.

php 7.1 intval behaving weird? [duplicate]

This question already has answers here:
Why does `intval(19.9 * 100)` equal `1989`?
(5 answers)
Closed 4 years ago.
i am doing some calculation where i noticed intval weird behavior
which is making a whole lot of mess because i just want int part of whole variable but intval is stabbing me in the back in comparisons. Any ideas why its behaving like that and what i can use for my requirement?
intval( 9.62 * 100 ) //gives 961
(int)( 9.62 * 100 ) // gives 962.0
my tried methods to achieve my goals were:
floor(9.62 * 100) // but its giving 962.0 no acceptable
This should work for you.
intval(strval( 9.62 * 100));
It seems to be a problem with the precision of floating points, and converting the number to string and then to int seems to fix the problem.
Here is a link to the documentation, http://php.net/manual/en/language.types.float.php
As it states,
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....
echo intval((0.1 + 0.7) * 10); //returns 7
echo intval(strval(0.1 + 0.7) * 10); //returns 8
Since (int) always rounds the number down, a small error in the representation makes the cast round it one number down that you would otherwise expect.
I tried sprintf('%.40F', 9.62 * 100.0);, and get this: "961.9999999999998863131622783839702606201172".
Thats why intval( 9.62 * 100 ) gives you 961.
You can try to use bcmul()
(int) bcmul(9.62, 100);
Please try this
ceil(9.62*100);

PHP float and int return a different number [duplicate]

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 6 years ago.
I have been scratching my head at this VERY odd problem. I do some calculations in PHP and the end result is a number. This is a whole number, but because calculations are done, PHP considers this a float. However, when I typecast it as an integer, it magically gets subtracted one. As in 1. A whole integer down. I really am at a loss. Try for yourself.
<?php
$number_of_rows = 10;
$number_of_columns = 19;
$active = array();
$tile = 160;
$column = $tile/$number_of_columns; // 8.42105263158
$rounded_down = floor($column); // 8
$column = $column-$rounded_down; // 0.42105263158
$column = $column*$number_of_columns; // 8
var_dump($column); // 8 -> that is great
var_dump((int)$column); // 7 -> WTF?!!!
?>
PHP 7.0.12 on Linux 64 bit.
See the Warning in PHP manual for an explanation.
Excerpt that talks about precision and a floor() example:
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....

PHP Strange Floating Point Imprecision

if I try to print
echo ((0.1 + 0.7) * 10);
output (http://codepad.org/m3mNNO77)
8
but if I try to print
echo (int)((0.1 + 0.7) * 10);
output (http://codepad.org/8OTCnlVG)
7
why two different results ?
If you perform the echo without the (int) cast, it resulits in:
echo ((0.1 + 0.7) * 10);
8
So what happens is that the floating point actually represents it as 7.99999....
When you perform an (int) cast, the default behavior is to take the integral part, so that's 7. Although it is extremely close to 8, it is not the behavior of a cast to round off.
The errors are due to the fact that floating point numbers are represented with a binary radix. Representing 0.8 correctly is thus impossible. Floating points round off the answers, and hope it doesn't bother that much. When you represent the floating point like 0.8, the result is 0.80000...
Proof of concept using the PHP interactive shell (php -a):
$ php -a
Interactive mode enabled
php > echo number_format(((0.1 + 0.7) * 10),20)."\n";
7.99999999999999911182
php > echo number_format(0.8,20);
0.80000000000000004441
As you may be aware, floating point math is not exact due to restrictions in their representation.
(0.1 + 0.7) * 10 works out to something like 7.99999999999....
When echo'd out, the number is converted to a string using rounding, which uses the php.ini precision setting (15 by default, I believe) to limit the number of decimal numbers. It happens that this rounding gives exactly 8.
However, (int) casts the float to an integer instead, and this is done with truncation. It doesn't matter how close to the next integer up you are, it will always round down. This is why you get 7 here.

How to emulate single precision float operations in PHP?

I need to port a simple C program to PHP. Currently we have to start the process and parse it's output. The program is very trivial but it is important for the algorithm to use float as the errors will sum up and the result will be way off.
C example:
#include <stdio.h>
int main( void ) {
printf("%f\n", 123456 * (float)0.99524);
printf("%f\n", 123456 * (double)0.99524);
return 0;
}
PHP example:
<?php
printf("%f\n", 123456 * 0.99524);
?>
The C example will result in 122868.343750 and 122868.349440 while PHP will end up with 122868.349440.
How do I get the C float result in PHP?
There is no way you can do this using built in php functions.
The one using "double" gives you the real result, 100% precise. The float one is wrong.
In PHP float and double are the same type, which is double.
If you need high precision results, that always give the same results, try using BC Math module: http://php.net/bcmath
Example code using BC Math:
$result = bcmul("123456", "0.99524", 6); // gives 122868.34944
$result = number_format($result, 6, ".", ""); // 122868.349440 - appending zeros
echo $result;
Output:
122868.349440
If you really, really want the same result as in the C program, then you have 2 options:
Create your own c-like function by writing a php extension: http://www.google.com/search?q=writing+php+extensions
Talk to your C-program from PHP via function proc_open():
http://www.php.net/manual/en/function.proc-open.php (see also popen(), exec() or shell_exec())
You could always create a PHP module.
Here are a list of resources that I've compiled over time...
http://www.delicious.com/homer6/php+extension
Also, I'd highly recommend reading Sara Goleman's book:
http://blog.simonholywell.com/post/1156691738/15-excellent-resources-for-php-extension-development
Hope that helps...
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.
Quoted from : http://php.net/manual/en/language.types.float.php
To change the precision level of PHP , change the precision settings in php.ini

Categories