I have a simple problem but fairly complex and I could use some advice on how to solve it.
I've been trying all solutions of questions asked before but none of them seem to work.
echo dechex(0.258068 * 1000000000000000000); //returns 394d77a8be54020
The correct value however is
394D77A8BE54000
how can I convert it to the correct value, I understand is a big integer and that is a problem, but how can I obtain correct values inside my script ?
You're correct: you're getting a floating point inaccuracy error. Note that 0.258068 * 1000000000000000000 is a float, not an integer.
Here's a solution:
echo 0.258068 * 1000000000000000000;
echo PHP_EOL;
$i = bcmul(0.258068, 1000000000000000000);
echo $i;
echo PHP_EOL;
$h = dechex($i);
echo $h;
Result:
2.58068E+17
258068000000000000
394d77a8be54000
Refs:
Live example
bcmul
Related
As an example I have code similar to this:
$r1 = 7.39999999999999;
$r2 = 10000;
echo bcmul($r1,$r2,100);
//returns 74000.0
echo ($r1*$r2);
//returns 74000.0
I am wanting it to return 73999.9999999999 rather than rounding it off.
Is there a formula or function to do this?
The doc http://php.net/manual/de/function.bcmul.php says:
left_operand: The left operand, as a string.
right_operand: The right operand, as a string.
So use strings instead:
$r1 = "7.39999999999999";
$r2 = "10000";
echo bcmul($r1,$r2,100);
works.
Or if you have these varibales from somewhere cast them (via (string) ) to string. Maybe at this step you could encounter some roundings already...
I'm not a php person, but a quick Google suggests you may want the
$number_format()
function and specify the $decimals parameter. See this link
Hello now my code looks like:
echo number_format($_SESSION['price_summ']."<br>");
But I need to have numbers with decimals... I know it should look something like this:
$row['price'] = intval(($row['price']*100))/100;
But it Does not work.
The simplest way is to store your data in database with type of DECIMAL or FLOAT or DOUBLE. And when you will output data from database it will already be in decimal format. Which type to use is relative. Look threw the web to find optimal solution for your situation.
If you want to use PHP use number_format()
$num = "18";
echo number_format((float)$num, 2, '.', ''); //echo will output 105.00
Its really a lot confusing line
echo number_format($_SESSION['price_summ']."<br>");
I guess you want to convert $_SESSION['price_summ'] to float .
Use floatval() for it.
echo number_format(floatval($_SESSION['price_summ']))."<br>";
Alsi you put the bracket after "<br>" which is wrong. In your second code segment you ate simply doing nothing if you $row['price'] is an integer. If it is an integer, go for this
$row['price'] = intval(($row['price']*100.0))/100;
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 8 years ago.
I'm utterly confused why PHP is behaving the way it is below.
Context: I'm using a third party payment gateway library. For some reason some of my payments are getting charged 1c less! Which is a huge problem for us. To make things even more odd, it only seems to be for some specific amounts
Looking at their code I was able to reproduce this in a simple php script.
<?php
$val = 568.3 * 100;
echo $val;
echo "\n";
echo (float) ($val);
echo "\n";
echo (int) ($val);
echo "\n";
echo intval($val);
echo "\n";
?>
Expected output would be 56830 for all the echo's but instead, when its casting or using intval it prints out 56829 (1c less) and using no type cast or float works. The fix seems to be just not using int or intval conversions but am very curious why this is happening.
If you put in 56830 then it all prints fine. Reproduceable with 568.31 * 100 but not 568.32 * 100.
Can anyone help me understand whats happening?
EDIT: float / floatval / no casting returns the expected value.
The follow works, just when using 568.3 it loses 1 cent!
$val = 5.3 * 100;
$val = 56888.3 * 100;
FuzzyTree's answer explained the problem with floating point arithmetic. You can fix it by using round before intval.
<?php
$val = 568.3 * 100;
echo $val;
echo "\n";
echo (float) ($val);
echo "\n";
echo (int) (round($val));
echo "\n";
echo intval(round($val));
echo "\n";
?>
Output:
56830
56830
56830
56830
$val is float with a value of something like 56829.999999... and it gets rounded down when converting to an int.
From the manual
http://www.php.net/manual/en/language.types.integer.php
From floating point numbers ΒΆ
When converting from float to integer, the number will be rounded
towards zero.
If the float is beyond the boundaries of integer (usually +/- 2.15e+9
= 2^31 on 32-bit platforms and +/- 9.22e+18 = 2^63 on 64-bit platforms other than Windows), the result is undefined, since the float doesn't
have enough precision to give an exact integer result. No warning, not
even a notice will be issued when this happens!
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 />";
?>
get this from my database:
252.587254564
Well i wanna remove the .587254564 and keep the 252, how can i do that?
What function should i use and can you show me an example?
Greetings
You can do it in PHP:
round($val, 0);
or in your MYSQL statement:
select round(foo_value, 0) value from foo
You can do a simply cast to int.
$var = 252.587254564;
$var = (int)$var; // 252
As Tricker mentioned you can round the value down or you can just cast it to int like so:
$variable = 252.587254564; // this is of type double
$variable = (int)$variable; // this will cast the type from double to int causing it to strip the floating point.
In PHP you would use:
$value = floor($value);
floor: Returns the next lowest integer value by rounding the value down if necessary.
If you wanted to round up it would be:
$value = ceil($value);
ceil: Returns the next highest integer value by rounding the value up if necessary.
You can just cast it to an int:
$new = (int)$old;
Convert the float number to string, and use intval to convert it to integer will give you 1990
intval(("19.90"*100).'')
Before using above answer what is your exact requirement please see bellow example output.
$val = 252.587254564;
echo (int)$val; //252
echo round($val, 0); //253
echo ceil($val); //253
$val = 1234567890123456789.512345;
echo (int)$val; //1234567890123456768
echo round($val, 0);//1.2345678901235E+18
echo ceil($val); //1.2345678901235E+18
$val = 123456789012345678912.512345;
echo (int)$val; //-5670419503621177344
echo round($val, 0);//1.2345678901235E+20
echo ceil($val); //1.2345678901235E+20
you can use echo (int) 252.587254564;
positive number:
round(252.587254564) // 253
floor(252.587254564) // 252
ceil(252.587254564) //252
(int)252.587254564 // 252
intval(252.587254564) // 252
~~252.587254564 // 252
negative number:
round(-252.587254564) // -253
floor(-252.587254564) // -253
ceil(-252.587254564) // -252
(int)-252.587254564 // -252
intval(-252.587254564) // -252
~~-252.587254564 // -252
if you want just remove decimals without round you can use one of above codes except round and floor(for negative number).
But I recommended the last one, it's simpler and faster using prefix ~~
And there is also a not quite advisable method:
strtok($value, ".");
This cuts of the first part until it encounters a dot. The result will be a string, not a PHP integer. While it doesn't affect using the result much, it's not the best option.
I see many answers, but the question is:
"Well i wanna remove the .587254564 and keep the 252, how can i do
that?"
Since the questioner is asking for php, the function in php will be the one for the job.
$newValue = floor($value);
In MySQL you can use:
select floor(field)
or in PHP you can use:
floor($value);