PHP precision limitation - php

I'm having trouble about getting the exact value in PHP.
I have these values :
$a = 22900000.002827;
$b = 0.022900;
$c = $a/$b;
I'm expecting to have a result of 1000000000.12345 but it only return 1000000000.1234
My question is that, is there any way to bypass this limitation in PHP?

PHP's floating point numbers are platform-dependent, however with the proper formatting print and on a 64bit build you should be able to get the desired result:
printf("%.5f", 22900000.002827 / 0.022900);
// on my system, prints: 1000000000.12345
If you want to print "up to 5" decimal places, but with no tailing zeros it they are not needed you can use the g format type:
printf("%.5f", 1/2);
// prints: 0.50000 - this is pretty ugly
printf("%.5g", 1/2);
// prints: 0.5
printf("%.5g", 22900000.002827 / 0.022900);
// prints: 1.0e+9 unfortunately
print rtrim(sprintf("%.5f", 22900000.002827 / 0.022900), "0");
print rtrim(sprintf("%.5f", 1/2), "0");
// prints: 1000000000.12345 and 0.5

you can use bcdiv and supply no of digits what you want after decimal like
<?php
$a = 22900000.002827;
$b = 0.022900;
$c = $a/$b;
echo " c=".$c;
$d = bcdiv("$a", "$b", 5);
echo " d=".$d;
?>
OUTPUT :
c=1000000000.1234
d=1000000000.12344
Demo

Related

Returning a "readable" number in PHP

I am trying to receive a result of a math operation with small numbers (maximum 8 decimals), I receive a float result, but in a format that make the other numbers stay with an error:
$a = round($x, 8); //returns 0.0478674, that's correct
$b = round($y,8); //returns 0.04786261, that's correct
$z = $a - $b; //z returns 4.7899999999976E-6, and not ‭0.00000479‬ as I was expecting
I tried as well
$w = round($z,8); //but w returns 4.79E-6, and not 0.00000479‬ as I was expecting
My problem is because the number 4.7899999999976E-6 give an error in other calcs and it's a ugly number to show to the user.
How can I make this number be 0.00000479‬?
you can use number_format:
$w = number_format($z,8);
number_format should do what you require, from the help: https://www.php.net/manual/en/function.number-format.php
For your specific requirement here:
$w = number_format($z,8);

Float division returning int - PHP 7

Doing what should be a straight forward calculation in PHP 7. The following never produces a float result. Running var_dump($C) returns int(2)
$A = 0.04;
$B = 0.20;
$C = 3*($A/$B)^2;
echo $C;
I don't need the result to be float type, I need the precision.
I've tried setting the precision using ini_set('precision', n). I've tried the code on three environments and getting the same result. Declaring (float) is also does not work.
What am I doing wrong?
3*($A/$B)^2
Means 3 * (A/B) XOR 2 (^ means xor) so bascially the result you are seeing is the result of a bitwise XOR on the result of your division.
If you want to raise the result to the power 2, you should use the pow() function. You can read about it here: http://php.net/manual/en/function.pow.php .
^ does not calculate the power, but XOR (which casts float to int).
to calculate the power, use pow() or in PHP5.6+ **
<?php
$A = 0.04;
$B = 0.20;
$C = 3*($A/$B)**2;
echo $C; //output: 0.12
You should use pow() instead.
$C = 3 * pow(($A/$B), 2);
var_dump($C); // float(0.12)
try using
<?php
$A = 0.04;
$B = 0.20;
$C = 3 * pow(($A/$B),2);
echo $C; //output: 0.36

PHP : The awk subtraction giving exponential values

I am getting awk result when I am subtracting two values, the error is I am getting exponent value 2.7755575615629E-17 instead of 0. Anything I am missing to apply, please suggest. These is happening with some cases only like 0.66, 0.67, 0.33,
The prototype of the code I am using is given below,
$_SESSION['x'] = 1;
$_SESSION['x'] = $_SESSION['x'] - 0.83;
echo ( $_SESSION['x']- 0.17) ;
echo '<br>';
But on reversing the values It all fine with 0
$_SESSION['x'] = 1;
$_SESSION['x'] = $_SESSION['x'] - 0.17;
echo ( $_SESSION['x']- 0.83) ;
echo '<br>';
This is because its the floating point numbers. And as per the 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). "
http://php.net/manual/en/language.types.float.php
Now there are 2 things which could be done by using the type cast your result to (int) or round up the result.
The other option is to use the sprintf
Here is an example
$a = 0.00001234;
echo $a ;
The output will be as
1.234E-5
Now if we do
echo (int)$a ;
The output is 0
or
echo round($a) ;
output will be 0
And finally if we do
echo sprintf('%f', $a);
We will get 0.000012
It is a common problem in computer languages - float values aren't represented exactly. See also http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems. If you have a particular amount of decimal places you want to exactly calculate with, you can use the bcmath functions in PHP:
$_SESSION['x'] = 1;
$_SESSION['x'] = bcsub($_SESSION['x'], 0.83, 10);
echo bcsub($_SESSION['x'], 0.17, 10);
echo '<br>';
Otherwise you can simply use your calculation and add an round($result, $numberOfDecimalPlaces) to you calculated result.

Error With Using (int) and (double) together to Cut off Decimals

When I am using (int) with (double) some times it is not working correct.
Look At The PHP Code Example:
I Need To LEAVE 2 Decimals And REMOVE Other...
I Know number_format(); function But I Cannot Use It. Because It Is Rounding Number
number_format(24.299,2);
Output: 24.30
I Need: 24.29
<?php
$str="158.2";
echo (double)$str; // Output: 158.2
echo (double)$str*100; // Output: 15820
echo (int)((double)$str*100); // Output: 15819 <-WHY? It Must To Be 15820, Why 15819?
echo ((int)((double)$str*100)/100); // Output: 158.19
?>
I need To leave two decimals in the number and cut other WITHOUT rounding.
Because of floating point precision (see for example this question: PHP - Floating Number Precision), 158.2 * 100 is not exactly 15820 but something like 15819.99999999.
Now (int) is for type conversion, not for rounding, and any digits after the point are cut of.
I need To leave two decimals in the number and cut other WITHOUT rounding.
This is easy:
number_format($str, 2);
Update
number_format does round, so it is a bit more complicated:
bcmul($str,100,0)/100
bcmul multiplies with arbitrary precision, in this case 0. Results:
bcmul(158.2,100,0)/100 == 158.2
bcmul(24.299,100,0)/100 == 24.29
This doesn't answer the question of why that happens (it could be a precision bug), but to solve your problem, try using $foo = sprintf("%.2f", (float)$str);.
Example:
$str = "158.2";
$num = (double)$str;
print sprintf("%.2f", $num);
EDIT: Infact, yes, this is a precision issue. (in C++) by printing 158.2 to 20 decimal places, I get the output of "158.19999999999998863132". This is an inherent problem with floating point/double precision values. You can see the same effect by using echo sprintf("%.20f", $var); in PHP.
First off, PHP is a language that allows you to type juggle. Which means you do not need the (int) or the (double) to do what you're trying to do.
<?php
$str="158.2"; //could also do $str = 158.2
echo $str; // Ouput: 158.2
echo $str * 100; //Output: 15820
echo number_format($str, 2); //Output: 158.20
echo number_format(($str*100)/100, 2); //Output: 158.20
?>
Use the number_format command to format your numbers how you want.
More here
Never cast an unknown fraction to integers, see the manual on http://www.php.net/manual/en/language.types.integer.php.
(int) ( (0.1+0.7) * 10 ); will result in 7, not 8 as one might expect. Casting from float to integer will always round down - and you may also want to check the operator precedence http://php.net/manual/en/language.operators.precedence.php.
Solution: calculate your fraction before you cast it. $fStr = (float) $str; $iStr = (int) $fStr;
Fixed.
function cutDecimals($number,$decimal){
$_str=(string)$number;
if(strpos($_str,".")!==false){
$dotPosition=strpos($_str,".")+1;
$_numCount=strpos($_str,".");
$_decimal=strlen($_str)-$dotPosition;
if($_decimal<$decimal) return (double)$_str;
else return (double)substr($_str,0,$_numCount+$decimal+1);
}else return (double)$_str;
}
echo cutDecimals("158.099909865",2)."<br />";
echo cutDecimals("14.02",2)."<br />";
echo cutDecimals("41.12566",2)."<br />";
echo cutDecimals("1.981",2)."<br />";
echo cutDecimals("0.4111",2)."<br />";
echo cutDecimals("144.2",2)."<br />";
echo cutDecimals("55.000000",2)."<br />";
echo cutDecimals("1456115.499811445121",2)."<br />";
?>

want to display exactly 2 digits after floating point

I want to convert floating value of 8 digits after floating point in to 2 digits after floating point ..
Eg. $a = 2.200000 ==> 2.20
I am using round function of php. Problem with round is if my number is 2.200000 it converts number in 2.2 . I want output as 2.20
Can any one suggest the possible way?
Actual code
$price = sprintf ("%.2f", round(($opt->price_value + ($opt->price_value * $this->row->prices[0]->taxes[0]->tax_rate)), 2));
i want out put like if my floating number is 2.2000000. then it should return me 2.20. but right now it is returning me 2.2
This does what I think you are asking for:
<?php
$a = 2.20032324;
$f = sprintf ("%.2f", $a);
echo "$a rounded to 2 decimal places is '$f'\n";
$a = 2.2000000;
$f = sprintf ("%.2f", $a);
echo "$a rounded to 2 decimal places is '$f'\n";
results:
[wally#lenovoR61 ~]$ php t.php
2.20032324 rounded to 2 decimal places is '2.20'
2.2 rounded to 2 decimal places is '2.20'
I added two test cases
i was working on it :D
$number='49.099998479854654656516198498465465465465';
function pure_decimal($number){
if(is_numeric($number) and floor($number)!=$number){
//decimal detected
$explode=explode('.',$number);
$first_no=$explode['0'];
$second_no=$explode['1'];
$get_only_two=substr($second_no,0,2);
$final_no=$first_no.'.'.$get_only_two;
$final_no=($final_no*1);
}else{
//normal
$final_no=$number;
}
return $final_no;
}
//result is 49.09
regards.
try $val = round($a * 100)/100;
Try the below code, You can get your result.
$a = 2.200000;
echo number_format((float)$a,2,'.','');

Categories