Why does PHP transform 15+ digit long integer on output [duplicate] - php

This question already has answers here:
round in PHP shows scientific notation instead of full number
(3 answers)
Closed 9 years ago.
Why does echo 100000000000000; output 1.0E+14 and not 100000000000000?
This kind of transformation of integers on output happens only for integers that are 15 digits long and longer.

PHP will convert an integer to float if it is bigger than PHP_INT_MAX. For 32-bit systems this is 2147483647.
The answer to the questions is related to the string representation of floats in PHP.
If the exponent in the scientific notation is bigger than 13 or smaller than -4, PHP will use scientific representation when printing floats.
Examples:
echo 0.0001; // 0.0001;
echo 0.00001; // 1.0E-5
// 14 digits
echo 10000000000000; // 10000000000000
// 15 digits
echo 100000000000000; // 1.0E+14
See float vs. double precision

That number is too big to fit into a 32 bit integer so PHP is storing it in a float.
See the integer overflow section in the php manual.
On the off chance that you need really big integers, look into GMP.

PHP cannot handle integers that big, and therefore treats them as floats. Floats are typically represented in scientific notation to take into account the inaccuracies past a certain number of significant digits.

The number is too big to be stored as integer by PHP on your platform,
so it is stored as a floating-point number.
The rules of conversion to string are different for float-numbers and integers.
Try the following:
var_dump(100000000000000);
echo(is_int(100000000000000) ? 'an integer' : 'not an integer');
Output:
float(1.0E+14)
not an integer

Any number larger than PHP's built-in integer size is stored and represented as a float.
To format a number in a particular way on output, use a function such as printf .

Related

PHP expanding float value unexpectedly [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
Am having an issue where PHP expands the float value e.g. 241.09 becomes 241.0899999999. The issue is, the expanded value is included in a signature, thus the expansion is causing my signature to have a mismatch when matching with the actual data which has the original unexpanded form. How do I prevent the rounding off? My code section is as below:
round(floatval($resultParams["AvailableFunds"]), 2)
Somehow, even after applying the round function, the expansion still occurs. How do I prevent that??
It's caused by the PHP Floating point precision:
Floating point numbers have limited precision.
A solution may be to use only integer, e.g. save the float 123.45 as 12345 and when you need to use display it divide it by 100 and pass it to the number_format function:
$myNumView = number_format($myNum/100, 2, '.', '')+0;
By doing this, number_format returns a string formatted as 1234567.89, then by doing +0 PHP converts it to float (due to the PHP Type Juggling) and removes the rightmost 0 in the decimal part of the number:
$a = '35';
$b = '-34.99';
echo $myNum = ($a + $b);
echo '<br>';
echo $myNumView = number_format($myNum, 4, '.', '')+0;
returns:
0.009999999999998
0.01
And also, why does you get AvailableFunds from a string with floatval? It seems that AvailableFunds is a string containing the amount of fund and other text. I think this is a bad implementation on how saving the fund amount. It's better to save the value as is in a dedicated field as float.

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 expression output [duplicate]

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.

PHP: Limits when Counting with float values

I need to count numbers but have to use a float datatype (don't as why - it's kind of an embedded system).
The simple counter goes like:
$num=1.0;
do {
$num = $num + 1;
// do some stuff
// ...
} while (...);
Question 1: What is the biggest number that can be counted correctly using a 32-bit and a 64-bit PHP system?
Question 2: When $num is read from a MySQL database using a standard FLOAT type (no precision specified) at the beginning of the loop and stored back at the end of the loop, is the answer to Question 1 still valid?
PHP uses double precision floating point, which has a 52-bit mantissa. This means that integers represented using floats start losing precision when they reach 253 (the extra bit of precision is because the leading bit of a normalized mantissa is always 1, so this doesn't need to be included explicitly in the representation). The following example demonstrates this:
echo number_format(pow(2.0, 53)-1) . "<br>" .
number_format(pow(2.0, 53)) . "<br>" .
number_format(pow(2.0, 53)+1);
outputs:
9,007,199,254,740,991
9,007,199,254,740,992
9,007,199,254,740,992
To get equivalent floating point precision in MySQL you should use the DOUBLE datatype, which is 64-bit floating point. If you just use FLOAT you'll get 32-bit single precision, which only has 23 bits of mantissa, and loses integer precision at 16,777,216.
See FLOAT and DOUBLE Data Type Representation for more details about how MySQL stores floating point internally.

Large numbers in PHP

I've been playing around with large numbers in PHP and was just wondering what module/process it uses to calculate the large numbers, and why it isn't used for all PHP numeric functions.
Hope this explains it a little better
My PHP_INT_MAX is 2147483647 (31 bits)
But, I figured out can create a 1017 bit number, by using:
$largenumber = pow(142,142);
This number is 310 digits long so I wont paste it in here ...
But then if I then try convert it to binary:
decbin($largenumber);
I get 1111111111111111111111111111111 (31 bits ... PHP_INT_MAX)
So, if the pow() function can handle this large number, why can't the decbin() function handle it?
From the official PHP documentation on pow:
base raised to the power of exp. If both arguments are non-negative
integers and the result can be represented as an integer, the result
will be returned with integer type, otherwise it will be returned as a
float.
$largenumber = pow(142,142);
var_dump($largenumber); //float(INF)
pow returns a float, which decbin tries to convert to an int and where you exceed the maximum integer value.

Categories