When I print this number in php 137582392964679 I get this as the output 1.37582392965E+14
All I am doing is a simple
print 137582392964679;
Anyone know why it's doing this? It's as if it's converting to an exponential number automatically. Someone said it's because I'm on a 32 bit machine. If that's the case how can I get around this problem?
Thanks
Check the const PHP_INT_MAX. You're likely over the max, which is typically around 2 billion for a 32bit system.
The maximum number you can store in a signed integer on a 32-bit machine is 2147483647. You can store numbers larger than this in a float but you risk losing some precision.
If that's the case how can I get around this problem?
You probably want to use a big number library. Try GMP:
$sum = gmp_add("123456789012345", "76543210987655");
echo gmp_strval($sum) . "\n";
Result:
200000000000000
Another alternative you could use is BC Math.
If you don't need to do any calculations with these numbers, but just store tham correctly, then store them as strings rather than integers.
I am on a 64 bit machine and it does the same thing. You might want to try using: print number_format(137582392964679);
That number is too big to fit into a 32-bit integer, so yes, it is converting to a floating point type automatically. How to get around it depends on the requirements of your system. If you aren't going to do any arithmetic then just store it as a string. If precision isn't overly important then you could leave it as a float and format it using printf. If precision is important and you can upgrade to 64-bit that should fix it, if you can't upgrade and you need an integer then you could look into using the BC Math PHP extension.
The manual clearly says:
If PHP encounters a number beyond the
bounds of the integer type, it will
be interpreted as a float instead.
Also your number cannot be represented accurately because of inherent floating point limitations, hence it is being approximated.
Related
var_dump((float)'79.10') returns me 79.09999999999999. I've tried a million ways to try and round this value up to the original 79.10 as a float (number_format, round), and I can't find a way to do it.
Is there any way I can get a float value of 79.10 from the original string?
No, because 0.1 (and, by extension, 79.1) is not actually representable as a float (assuming IEEE-754 single or double precision encoding). 0.1 in that encoding has an infinitely recurring fractional part:
1001 1001 1001 1001 ...
You'll either have to leave it as a string or accept the fact that the encoding scheme does not have infinite precision and work around it.
An example of the latter is to only output the numbers to a certain precision, such as two decimal digits, and to make sure that (in-)equality comparisons use either absolute or relative deltas to compare numbers.
When you're adding numbers, it takes quite a few operations for the imprecision effects to become visible at the hundredths level. It's quicker when multiplying but still takes a while.
While paxdiablo is right and working with floats does not have infinite precision, I've discovered that it is indeed possible to represent 79.10 as a float by first adjusting PHP's precision setting:
ini_set('precision', 15);
After that, var_dump((float)'79.10') correctly returns a float of 79.1. The different results that everyone is seeing on their own machines seems to be a result of everyone having different precision values set by default.
This is impossible as a float because it does not offer enough precision (see here for more information)
Now, in most languages you could cast it to a double... Unfortunately, in PHP, float and double use exactly the same underlying datatype so in order to get the value you want, you would have to recompile PHP.
Your best option would be to use something like the PHP BCMath module for arbitrary precision.
I resolved the issue with the code that i was working, but this is something that bugs me out.
I know that floating point in certain circumnstances just messes up with rounding.
I know that php uses types inferences, and there is an automatic cast when you operate aritmetically between strings (i mean, in this particular case, in my example).
Doing the same thing 'by hand in code', result of 160.2 * 50 is 8010, when there is no need for rounding when casting to the integer result. Is just ackward.
If anyone knows why this happens, it will enlightment me.
echo "160.2" * "50"; // gives 8010
echo (int) ((float)"160.2" * (int)"50"); // Gives 8009
I solved the issue and my code is working now; this is just for fun. I want to know why and how, step by step php messes up with this. Where is php losing resolution? In what step?
Thanks in advance :)
PHP represented (float)"160.2" as the binary equivalent of 160.19999999995343387126... internally. That would cause the multiplication result to be slight smaller than 8010, which on casting back to int, causes truncation and leads to 8009
160.2 in binary cannot be perfectly represented. It comes out to be a recurring decimal,
10100000.00110011001100110011001100110011...
So you cannot expect it to be accurately represented with float.
(Converter)
Where is php losing resolution? In what step?
When you are casting the result to int. Originally, result is in float, if you increase precision in php settings, you will see that it is something like 8009.9999999999990905052982270718, casting positive numbers to int is basically same as calling floor(), that's why it prints 8009.
I'm writing a PHP script that looks through a DB table of float values, that tend to be somewhat small, such as:
0.00052
0.00134
0.00103
0.00149
0.00085
0.00068
0.00077
0.00088
0.00169
0.00063
For reasons unknown to me, some values appear in the DB in scientific notation, such as:
1.12305e-06
The table is set to float, and I've tried all manner of functions in PHP to force the numbers to display as decimal, to no avail. Try as I might, I'm unable to get this table of numbers to be consistently decimal in all cases.
Any suggestions on how to resolve this? Have tried typcasting to (float) and using number_format() and several other options, but no change every time.
There seems to be a six digit limit on what is shown out of the CLI (and probably elsewhere). The example you have is 1.12305e-06 which is 0.00000112305 which would be shown as 0.00000 - though clearly it isn't zero.
If you are insisting on using floats or doubles, you will have to force them out using something like round(columnName,5) to force the display in a decimal value. Otherwise, maybe switch to a decimnal data type.
From http://dev.mysql.com/doc/refman/5.0/en/floating-point-types.html
Because floating-point values are approximate and not stored as exact values, attempts to treat them as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies. For more information, see Section C.5.5.8, “Problems with Floating-Point Values”
Also see this thread on the mysql forums about this exact issue.
The solution in my case turned out to be changing from float to decimal type in the database, so thanks to Romain for the comment that led me to look into that solution!
I need to store a huge number in a PHP variable (it's for a programming contest if you're wondering why). However, if the number is too big, it gets displayed as 6.2995416979471E+77. Is there a way to store that huge number in PHP?
integers have a limited size of 32 or 64bit, depending on your architecture.
floats can store values of any size, but are imprecise.
If you want to work with giant, precise numbers, use strings and the BC Math extension.
$bigNumber = 1234567890; // etc
echo number_format($bigNumber, 0);
Have you tried PHP's BCMath arbitrary precision functions? They use strings to represent numbers.
Need something like intVal() but for bigger numbers, for example: 100001416147426.
Is there a function like this in php? Can't find it.
You should use BC Math, it is designed to numbers of any size with PHP.
The BC Math extensions offers several mathematic functions like:
bcadd Add two arbitrary precision numbers
bccomp — Compare two arbitrary precision numbers
bcsqrt Get the square root of an arbitrary precision number
...
On the PHP documentation site there is a small code example by Charles to round a long number!
consider
$x = (double) "100001416147426";
var_dump($x);
output:
float(1.0000141614743E+14)
coding standard in the past (since C) has been to follow the number with an L/l
$x = 100001416147426L;
This cue's the parser to allocate 64 bits in order to read the number out of the script to compile.
But unless you are running the php x64 this will be useless. Other wise you will have to build it out of a big_number component. Once in a x64 environment intval will automatically expand to a long when exceeding a 32-bit int.