Let's say I have:
echo 1/3;
And it print out only 0.33333333333333, can I get more digits?
Can use bcdiv
echo bcdiv(1, 3, 20);
The third argument
is used to set the number of digits after the decimal place in the result. You can also set the global default scale for all functions by using bcscale().
Edit the precision configuration variable either in your php.ini or some other configuration location or use ini_set().
ini_set('precision', 22);
echo 1/3;
// 0.3333333333333333148296
Even though I highly doubt that you really need that kind of precision ;-)
EDIT
As Gordon said: you'll hit the floating point precision limit in PHP sooner or later (depending on the precision specified). So the better way would be to use either the BCMath Arbitrary Precision Mathematics extension or the GNU Multiple Precision extension, if you're after real high precision mathematics.
You might want tto look into the BC arbitary precision php library
http://php.net/manual/en/book.bc.php
The setting is precision: http://es.php.net/manual/en/ini.core.php
However, I would not use it except for debugging purposes. Have a look at number_format()
Related
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 5 years ago.
I have this simple substraction code:
<?php
$n1 = 257931.076;
$n2 = 257930;
echo $n1 - $n2;
?>
Why i got 1.0760000000009 instead of 1.076
Where did the 0000000009 came from? i need precise result and i don't want to use round() or number_format() because sometime i have more than 3 decimal, for example: 12345.678912, anyone know?
I have tried to use round() or number_format() but it only for fixed decimal point, not dynamic
As #GordonM perfectly explained it, you cannot expect exact results when using floating point values.
You can use a library such as brick/math to perform exact calculations on decimal numbers of any size:
use Brick\Math\BigDecimal;
$n1 = BigDecimal::of('257931.076'); // pass the number as a string to retain precision!
$n2 = 257930;
echo $n1->minus($n2); // 1.076
The library uses GMP or BCMath internally when available, but can work without these extensions as well (with a performance penalty).
For technical reasons that every programmer should be aware of, IEEE floating point numbers simply can't represent numbers precisely and will use the closest approximation they can when storing them (In fact the only fractions that can be stored perfectly have denominators that are powers of 2 (1/2, 1/4, 1/8, 1/16, etc. All other values are approximations). PHP has an ini value called "precision", which controls how many digits are considered significant WHEN OUTPUTTING floating point values. It defaults to 14, with any digits after that hidden.
However, the actual value stored may try to approximate the desired value with far more digits than that. If you change precision, you'll see what is really being stored.
php > $test = 0.1;
php > var_dump ($test);
php shell code:1:
double(0.1)
php > ini_set("precision", 100);
php > var_dump ($test);
php shell code:1:
double(0.1000000000000000055511151231257827021181583404541015625)
php > var_dump (0.25);
php shell code:1:
double(0.25)
php > var_dump (0.4);
php shell code:1:
double(0.40000000000000002220446049250313080847263336181640625)
What can you actually do about this? Not a great deal, this is just a consequence of how floating point works. You can try to avoid using floating point if you need exact values (for example when dealing with money amounts, store 3.99 as 399 pennies/cents instead of 3.99 pounds/dollars), or you can use the "bugnum" libraries that are available in PHP, GMP and BC_Math, but these are both tricky to use and have their own sets of gotchas. They can also be hard on storage and/or processor time. In most cases it's best to just live with it and be aware that when you're dealing with floating point you're not dealing with an exact representation.
I am retrieving some values stored as string which have up to 15 decimal places. I need to json_encodeit and pass it on to javascript as numeric value. So I tried (float)$number, but the number gets rounded-off in this approach. How else can I convert it to number without any rounding?
You should use the GMP library in PHP whenever number precision is important. You may have to enable it inside of your php.ini settings. Search for...
;extension=php_gmp.dll
and change it to
extension=php_gmp.dll
and then you'll be able to use the GMP objects.
If you want to preserve those decimals: don't parse it. Any number converted to float is subject to precision loss. Can't you just print the variable as received in JS?
I would like to use base_convert function to convert 60 bit binary data to Hex code as follows. But the result is not correct. The output of the code below is 4e08556312ffc00 but the correct output is 4E08556312FFBFF.
Can anybody tell me why? is 60 bit too large to the function?
echo "The beacon ID in Hexadecimal is".base_convert
("010011100000100001010101011000110001001011111111101111111111",2, 16);
Thank
I have posted an implementation of a base conversion function without such limits in my answer to another question here.
According to base_convert and floating numbers documentation, base_convert will lose precision on large numbers.
Instead of, you can use bin2hex, which is not limited (this function use and return strings)
My tests reveal a loss of precision over 43bits.
I work on a Win XP base + easyphp 3.1.81 with default settings.
I use this base_convert for a genealogical application, and the limit of 43 generations is - sometimes - not enough.
It is the larger of:
PHP_INT_MAX and
The maximum of the contiguous set of integers that can be expressed as a float.
Typical PHP implementations use IEEE 754 for implementing floating point numbers, which has a 53-bit significand, so the typical limit for 32-bit environments is 2⁵³ (0x20000000000000) and for 64-bit environments, the limit is 2⁶³-1 (0x7fffffffffffffff).
There’s a trivial solution if you have the PHP gmp extension ( http://php.net/gmp ):
$hexNumber = gmp_strval( gmp_init( $binNumber, 2 ), 16 ) ;
If you have the bc extension (http://php.net/bc ), my (free & open source) WeirdoCustomDigits module will do conversions with arbitrary bases and arbitrary digit characters, without limitation.
If you're simply converting between base 2 and base 16, as with your example, you can get by without bc or gmp. See the source in the WeirdoCustomDigits module for WeirdoCustomDigits::binFromHex() and WeirdoCustomDigits::hexFromBin().
I need to port a simple C program to PHP. Currently we have to start the process and parse it's output. The program is very trivial but it is important for the algorithm to use float as the errors will sum up and the result will be way off.
C example:
#include <stdio.h>
int main( void ) {
printf("%f\n", 123456 * (float)0.99524);
printf("%f\n", 123456 * (double)0.99524);
return 0;
}
PHP example:
<?php
printf("%f\n", 123456 * 0.99524);
?>
The C example will result in 122868.343750 and 122868.349440 while PHP will end up with 122868.349440.
How do I get the C float result in PHP?
There is no way you can do this using built in php functions.
The one using "double" gives you the real result, 100% precise. The float one is wrong.
In PHP float and double are the same type, which is double.
If you need high precision results, that always give the same results, try using BC Math module: http://php.net/bcmath
Example code using BC Math:
$result = bcmul("123456", "0.99524", 6); // gives 122868.34944
$result = number_format($result, 6, ".", ""); // 122868.349440 - appending zeros
echo $result;
Output:
122868.349440
If you really, really want the same result as in the C program, then you have 2 options:
Create your own c-like function by writing a php extension: http://www.google.com/search?q=writing+php+extensions
Talk to your C-program from PHP via function proc_open():
http://www.php.net/manual/en/function.proc-open.php (see also popen(), exec() or shell_exec())
You could always create a PHP module.
Here are a list of resources that I've compiled over time...
http://www.delicious.com/homer6/php+extension
Also, I'd highly recommend reading Sara Goleman's book:
http://blog.simonholywell.com/post/1156691738/15-excellent-resources-for-php-extension-development
Hope that helps...
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 progragation 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 never
compare floating point numbers for equality. If higher precision is
necessary, the arbitrary precision math functions and gmp functions
are available.
Quoted from : http://php.net/manual/en/language.types.float.php
To change the precision level of PHP , change the precision settings in php.ini
everytime I try to get the factorial of 171, I get INF. 170 works fine. Is it possible to get the factorial of 171+ in a script? How?
My function:
function factorial($n) {
if ($n == 0) return 1;
return $n * factorial($n - 1);
}
If you deal with very large numbers, you'll need to use an extension that allows you to do that.
There's BCMath ( http://www.php.net/manual/en/book.bc.php) , and GMP ( http://www.php.net/manual/en/book.gmp.php ).
You'll have to use BC Math or GNU MP extension. PHP doesn't provide any tools for high-values or high-precision operations OOTB.
echo "1241018070217667823424840524103103992616605577501693185388951803611996075221691752992751978120487585576464959501670387052809889858690710767331242032218484364310473577889968548278290754541561964852153468318044293239598173696899657235903947616152278558180061176365108428800000000000000000000000000000000000000000"
really though, your function is fine. I think PHP lacks that kind of precision. I got the value (it is correct btw) in python
You are probably getting a value that exceeds the maximum double precision float in a 32-bit machine (~10^308). 170! factorial is ~7.25741562 × 10^307 which is just under that, however, 171! is larger. Your best bet is to use one of the libraries EboMike or Crozin recommends in their answers.
For large n, you can compute n! very quickly with little error using Stirling's approximation. Take a look at this post; it has an analysis of the function and some sample code:
http://threebrothers.org/brendan/blog/stirlings-approximation-formula-clojure/
It's a bigger number than you can hold using 32-bits. If you run the same code on a 64-bit computer then it should work.