This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
On My PHP server Float values changes when i print on website in json format.
but working ok on localhost.
Code:
$float = 1.440030394;
$value = round($float,5); // 1.44003
$response = array();
$response['status'] = true;
$response['message'] = "success";
$response['values'] = $value;
echo json_encode($response);
// test if value is really true?
echo "<br>test<br>";
echo $value."-abc"; // Work ok if float convert to string
Localhost Response is ok, but on Live server response is
{
"status": true,
"message": "success",
"values": 1.44035442150000012452200154
}
Test
1.44003-abc
Any solutions? i try functions : round, number_format but not working.
Float uses mantissa and exponent representation to hold a number. That means that not all bits of the value are saved separately, and this results in an impossibility to represent all numbers.
You can see this for more details: How are floating point numbers stored in memory?.
Basically your number cannot be stored in a float, so any operations you do on it will result in a slight error.
You have 2 options here.
First one is that if the error is not too big for you and you can ignore it, you just need to truncate the number on output result.
Second one is to treat the number like a string or save each individual digit inside an array. This is actually what happens when you converted your number to string on your last edit. Your number is not a number any more, but a string and each of its digits are saved individually.
Almost all languages are based on float for numbers with decimals because of their versatility, but floats should not be used for data where each bit is important (like for money). You can open your console in browser (f12 by default and type 0.8 - 0.7) the output will be 0.100000000009 or something like that, because 0.1 doesn't have an exact representation, but the error is small enough to be ignored usually.
Related
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.
I'm executing the following code in a PHP script:
$obj = new \stdClass();
$obj->lat = 0.000011399388312455;
echo json_encode($obj) . "\n";
The output of the script is
{"lat":1.1399388312454999446e-5}
As you can see, the number is represented in exponential notation.
Is there some way to represent that particular number in extended notation, in the JSON-serialized object?
The desired output is
{"lat":0.000011399388312455}
The version of PHP is 5.6.30.
P.S.: This JSON-serialized object will be sent to an external web service that doesn't accept numbers in exponential form. Moreover, it needs to be a number and not a string ({"lat":"0.000011399388312455"} won't work).
The number should not be rounded (it's a geographical coordinate).
Here are other similar questions, but they don't fit my case unfortunately.
php- floating point number shown in exponential form
Remove the "E" in a number format for very small numbers
Thank you in advance.
It is implemented in PHP 7.1 https://wiki.php.net/rfc/precise_float_value
As a work around, use other JSON serializers not a default json_encode.
E notation is valid form of float representation. In php >7.1 with precision set to -1 results of your code would look like: {"lat":1.1399388312455e-5} which is absolutely the same as 0.000011399388312455 because you have 4 leading zeros.
If you still want to have leading zeroes in json i would go towards strings. They are perfectly fine for coordinates representations.
This question already has an answer here:
Convert exponential to a whole number in PHP [duplicate]
(1 answer)
Closed 7 years ago.
I have data from csv, the contents of the column id look like this 6.61884E+17 6.61881E+17 6.61878E+17
This code not work, the results of this code remains the same :(
$a = '6.61884E+17';
$b = (string) floatval($a);
How to convert 6.61884E+17 to string ?
Update :
I try number_format(6.61884E+17,0,'','') and get 661884000000000000 as result. . my expected result is 661883847445868544
You want the number 661883847445868544 to be extracted from 6.61884E+17.
This isn't possible for you because of "integer overflow".
PHP handles this for you by converting it into a float (it's stupid because you can't perform basic arithmetic on them).
Now, if you run echo strval(661883847445868544); and get the same value back, you are running PHP 64 bit, and can handle that number. However, what is clear is that the program that created the CSV is 32 bit, and the largest integer values are:
2,147,483,647 signed
4,294,967,295 unsigned
After the value 6.61884E+17 is dumped, precision after the 6th digit is lost, and there is nothing you can do to bring it back. Sorry.
This question already has answers here:
Compare floats in php
(17 answers)
Closed 8 years ago.
I am new to PHP and trying to perform a simple arithmetic addition and comparison. I have an array with some decimal values and after adding all the values, I am trying to compare it to 1. My array is:
$myArray=[0.2,0.7,0.1]
and my code is:
$sum=0;
foreach($myArray as $val){
$sum+=$val;
}
Here, the sum comes out to be 1. But when I compare it using the following code:
if($sum!=1)
{
echo "Good";
}
else
{
echo "Bad";
}
it echoes "Good".
However, when my array contains values 0.8 and 0.2, it echoes "Bad". Can anyone help me on this?
If you check the PHP docs on floating-point numbers: php.net/manual/en/language.types.float.php, there is a huge warning on the page.
"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."
Thus, you could get unexpected results such as 0.2 + 0.7 = 0.900000000001. It's simply because computers have a hard time representing decimals. Binary was really built for integers.
Careful in your logic; I think you meant if($sum == 1) echo "Good", etc. In that case, 0.2+0.7+0.1 would echo "Bad", because it's totally possible that 0.2+0.7+0.1 = 1.00000001 or 0.99999999. On the other hand, adding a smaller number of floats together decreases the error, so 0.8+0.2 is more precise than 0.2+0.7+0.1.
This question already has an answer here:
The accuracy of PHP float calculate
(1 answer)
Closed 8 years ago.
I got a problem with PHP.
This exact substraction below is wrongly computed.
<?php
$test = 145.48 - 80.26;
if($test != 65.22)
echo 'not good !';
else
echo 'good';
?>
This echoes "not good" !!!
Why ?
Computers aren't very good at storing floating point (decimal) numbers since representing a base 10 decimal number in binary is hard. For instance, if you try to store the number 0.2 in binary, the computer will store a series following the pattern 0.00110011… . Depending on the size of the floating point number (i.e. how many bits have been allocated for it in memory), the precision will vary, but more important, it will never accurately store exactly 0.2.
There are several ways to fix this, one is using the BC Math library and do something like:
bcsub("145.48", "80.26");
But sometimes the better solution is to just acknowledge that the numbers won't be accurate and account for the error, i.e.
if (abs($x - $y) < $e)
where e is some very small number, e.g. 10^(-5). This is common practice when working with physics calculations and similar, but of course you should never attempt this when working with discrete numbers, e.g. currencies.
To do exact floating number arithmetic you can use bc_math:
$test = bcsub("145.48", "80.26");
assert ($test == "65.22");