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);
Related
I'm using bcmod and gmp_mod functions in php for handling large numbers.
This works fine:
// large number must be string
$n = "10000000000000000000001";
$y = 1025;
$c = 1025;
// Both works the same (also tested in python)
$y = gmp_mod( (bcpowmod($y, 2, $n) + $c) , $n);
$y = bcmod ( (bcpowmod($y, 2, $n) + $c) , $n);
But the input $n is not static. So I must use type casting like:
$n = (string)10000000000000000000001;
This doesn't work anymore.
for gmp gives this error:
gmp_mod(): Unable to convert variable to GMP - string is not an integer
And about bc, gives me this error:
bcmod(): Division by zero
The problem is, (string) doesn't convert it to string fine. Any idea?
Edit: I found a solution here, but still the input is string:
$bigint = gmp_init("9999999999999999999");
$bigint_string = gmp_strval($bigint);
var_dump($bigint_string);
If You are taking an input for $n it would give you as a string not as int and if you have type casted as int at any point ... taking care the max size of int, the above given no is converted to 1.0E+22 now what happens when you try to type cast (string)1.0E+22 it becomes "1.0E+22" which is obviously just a string and can not be converted to gmp number.
So You need to convert scientific notation to string which will auto include , hence you also need to replace those commas
$n = 10000000000000000000001;
$n = str_replace(",", "", number_format($n));
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
I got a few values I want to sum up and check agains another number like this:
$a = '15';
$b = '5,50';
$c = '-10';
$to_pay = '10,50';
$formated_total = number_format(($a+$b+($c)), 2, ',', ' ');
$this->assertEquals($to_pay, $formated_total);
the asser part is a selenium function I am using so dont think about that, it's just supposed to check if the 2 values are the same. Now the result I get is:
- Expected
+ Actual
-'10,50'
+'10,00'
Why am I losing the value from the decimals?
You should not use "," as decimal point it's not excel. In PHP you need to use DOT
Change your numbers to:
$a = '15';
$b = '5.50';
$c = '-10';
$to_pay = '10.50';
or even better solution would be treat them as numbers not as strings
Change your numbers to:
$a = 15;
$b = 5.50;
$c = -10;
$to_pay = 10.50;
In that way you would get error if you tried using , instead of .
You can also simplify this line:
$formated_total = number_format(($a+$b+($c)), 2, ',', ' ');
to
$formated_total = number_format($a+$b+$c, 2, ',', ' ');
You may be curious why the result is 10. It's because during casting it to number php parser checks in 5,50 the number at the begining which is 5 and ignores the rest.
From manual:
If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero).
Because comma is not a valid decimal point. You need to "convert" $b and $to_pay values to use dots.
I have the following code in a PHP script:
$sol = mt_rand(1,3);
I thought this was meant to return an integer but instead I'm getting a number with about 6 decimal places. How can I force it to return 1,2 or 3?
Thanks
You can use the ceiling or floor functions to round to an integer.
$sol = floor(mt_rand(1, 3));
$sol = ceil(mt_rand(1, 3));
How would you find the fractional part of a floating point number in PHP?
For example, if I have the value 1.25, I want to return 0.25.
$x = $x - floor($x)
$x = fmod($x, 1);
Here's a demo:
<?php
$x = 25.3333;
$x = fmod($x, 1);
var_dump($x);
Should ouptut
double(0.3333)
Credit.
Don't forget that you can't trust floating point arithmetic to be 100% accurate. If you're concerned about this, you'll want to look into the BCMath Arbitrary Precision Mathematics functions.
$x = 22.732423423423432;
$x = bcsub(abs($x),floor(abs($x)),20);
You could also hack on the string yourself
$x = 22.732423423423432;
$x = strstr ( $x, '.' );
The answer provided by nlucaroni will only work for positive numbers. A possible solution that works for both positive as well as negative numbers is:
$x = $x - intval($x)
If if the number is negative, you'll have to do this:
$x = abs($x) - floor(abs($x));
My PHP skills are lacking but you could minus the result of a floor from the original number
However, if you are dealing with something like perlin noise or another graphical representation, the solution which was accepted is correct. It will give you the fractional part from the lower number.
i.e:
.25 : 0 is integer below, fractional part is .25
-.25 : -1 is integer below, fractional part is .75
With the other solutions, you will repeat 0 as integer below, and worse, you will get reversed fractional values for all negative numbers.
Some of the preceding answers are partial. This, I believe, is what you need to handle all situations:
function getDecimalPart($floatNum) {
return abs($floatNum - intval($floatNum));
}
$decimalPart = getDecimalPart($floatNum);
You can use fmod function:
$y = fmod($x, 1); //$x = 1.25 $y = 0.25
To stop the confusion on this page actually this is the best answer, which is fast and works for both positive and negative values of $x:
$frac=($x<0) ? $x-ceil($x) : $x-floor($x);
I ran speed tests of 10 million computations on PHP 7.2.15 and even though both solutions give the same results, fmod is slower than floor/ceil.
$frac=($x<0) ? $x-ceil($x) : $x-floor($x);
-> 490-510 ms (depending on the sign of $x)
$frac=fmod($x, 1);
-> 590 - 1000 ms (depending on the value of $x)
Whereas the actual empty loop itself takes 80 ms (which is included in above timings).
Test script:
$x=sqrt(2)-0.41421356237;
$time_start = microtime(true);
for ($i=0;$i<=9999999;$i++) {
//$frac=fmod($x, 1); // version a
$frac=($x<0) ? $x-ceil($x) : $x-floor($x); // version b
}
$time_end = microtime(true);
$time = $time_end - $time_start;