I have a program that is giving me this number: 9.1466606511048E-8
I need to round that, using most obvious functions in PHP gives me 0.
That's because that number has a value of 0.000000091466606511048, which is very close to zero. Perhaps you need to be more specific about what sort of rounding you want.
How many decimals are you attempting to round to?
The number that you specified is the same as: 0.000000091466606511048
If you're using the round function without specifying to what decimal place you want to round, then it is going to round to zero because of the value.
Related
This question already has answers here:
Why is PHP printing my number in scientific notation, when I specified it as .000021?
(7 answers)
Closed 10 months ago.
I am using "(float)$val" for some calculation, but for some decimal value like -0.00000025478625
(float)-0.00000025478625 is resulting to -2.5479E-70,
i need the value same as that of -0.00000025478625, without affecting other scenarios.
how to prevent this conversion ?
I think you misunderstand the representation of your float. The value -2.5479E-70 actually is still a float value in scientific representation.
What this actually means is that your value is very small, so for readability reasons it is represented in this format. To read it you may replace the E with an multiplication of the following number to the power of 10 -2.5479 * 10^(-70). So this means that your floating point number is prepended with 70 zeros (which I wont write down here).
As example -5.47E-4 would be -5.47 * 10^(-4) which is the same as -5.47/10000 resulting in -0.000547.
Also, for printing your value was rounded. Internally it still uses the exact value. So if you use this number in further evaluations you do not lose any accuracy.
This is the scientific notation of float number. So, if you want to format then you should use number_format() function.
Below example the second parameter will tell at what precision do you need.
So, as per your example you should use 14.
Try this:
$var = number_format((float)-0.00000025478625, 14);
print($var);
Something to add to Manish's answer.
Please note that floating point numbers in PHP have limited precision:
For example:
<?php
echo number_format((float) 0.0000000000000000000000004, 50);
or even
<?php
printf('%f15.50', (float) 0.0000000000000000000000004);
You'd get something like this (depends on the system):
0.00000000000000000000000040000000000000001539794790
which is not exactly the original floating point number to print.
You can never count on the accuracy of floating point number. The best way to deal with them is to always store them as string until you need some calculation done.
In my php script I do a calculation of entries from a MySQL db. The concerning fields in the db are defined as decimal(10,3). It's an accounting plattform where I have to check if in every entry debit = credit.
I do this with the following operation:
$sumupNet = 0;
$sumup = 0;
foreach($val['Record'] as $subkey => $subval)
{
$sumupNet = $sumupNet + $subval['lc_amount_net'];
$sumup = $sumup + $subval['lc_amount_debit'] - $subval['lc_amount_credit'];
}
Now we say every entry is correkt, then $sumupNet and $sumup results in 0. In most cases, this works. But in some cases the result is something like this: -1.4432899320127E-15 or this -8.8817841970013E-15. If I calculate this values manually, the result is 0. I guess (not sure) that the above results are numbers near 0 and are outputted in the form of exponential.
So I think I have to convert something or my calculation is wrong. But what? I tried floatval() at some points but didn't work. If anybody has a hint, I thank you very much.
You're getting this because you are doing math with floating-point values. Read some theory about it.
You really don't want to calculate money like that as you might get weird rounding problems that you can't really do anything to fix.
For PHP, there are plenty of libraries that help you evade the problem, such as BC Math, or GMP.
Other solution would be to calculate all of the values using the smallest monetary value that the currency has (like cents) so you are always using integers.
These are rounding problems. These are perfectly normal when we are talking about floats. To give you an everyday example,
1/3 = 0.3333333333333333...333333333...3333...
Reason: 10 is relative prime with 3. You might wonder where is 10 coming from. We are using 10-base for numbers, that is, whenever we speak about a number, its digits represent 10-base exponential values. The computer works with binary numbers, that is, 2-base numbers. This means that division with such numbers often result in endless sequences of digits. For instance, 1/3 as a binary number looks like this:
0.010101010101010101010101010101010101010101010101010101...
Decimal types are representing decimal numbers, that is, 10-base numbers. You use three digits for the part after the . Let's supose your number ends like this:
.xyz
this means:
xyz / 1000
However, 1000 can be divided with the following prime numbers:
2 and 5.
Since 5 is relative prime with 2, whenever you are representing the result of a division by 5 as a binary number, there is a potential that the result will be an endless cycle of digits. 1/5 as a binary number looks like this:
0.0011001100110011001100110011001100110011001100110011...
Since a computer cannot store endless digits, it has to round the number, that is, find a number close to its value which can be represented in an easier manner. If the number a is rounded to b and the two numbers are not equal, then a certain amount of precision is lost and this is the reason of the bug you have mentioned.
You can solve the problem as follows: when you select the values from the database, multiply them by 1000 (thus, converting them into integers) and then check the operations. At the end, divide by 1000.
I've tried
$x = cos(deg2rad($angle));
but it returns 6.12323399574E-17 when the angle is 90 degrees instead of 0.
I read that this is a floating point problem, but is there a workaround?
6.1E-17 is almost zero anyway[*]. If you need to actually compare the result to zero, in floating point math you should check that it's within a certain tolerance of the desired value, since most numbers can't be represented correctly.
$x = cos(deg2rad($angle));
$is_zero = (abs($x) < 1e-10);
Strictly speaking, of course, zero is actually a number that can be represented correctly in floating point. The real problem is that pi / 2.0 can't be, so the input to your cos function isn't "correct".
[*] To put that in context, taken as a proportion of 1 AU (the average distance from the Sun to the Earth) it is equivalent to 0.0092 millimeters, or about a tenth of the average width of a human hair...
6.12323399574E-17 is an extremely small floating point number (17 zeros after the decimal point followed by a 6), almost indistinguishable from 0. If you are dealing with floating points (as any cosine function must), you can't avoid issues like this. If you need to compare a floating point number to zero, you must do it with error bars (i.e. is this number within a certain range of values around zero), not absolute comparison, even with simpler functions than cosine. If you just need to do some math with the result (add it, multiply it, whatever), it will behave almost exactly like zero so you won't need to worry.
Try this
$x = round(cos(deg2rad($angle)), 3);
I have one PHP script inserting rows in a MySQL database. Each row has a field 'created_at' which is filled with the value of the PHP function microtime(true), and inserted as a double. (microtime because I need something more precise than to the second)
I have another PHP script that selects rows based on that created_at field.
When I go ahead and select like this:
SELECT * FROM `ms_voltage` WHERE created_at > 1302775523.51878
I receive a resultset with, as the first row, the row with exactly that value for created_at.
This occurs from within my PHP script and from within PhpMyAdmin when manually doing the query. But not always, not for every value. Just once and a while really.
How is this possible? I didn't ask for greater than/equals, I want strictly greater than.
Am I overlooking something type-related perhaps?
Yeah, floating point arithmetic can do that sometimes. To understand why, it's helpful to realize that just as not all numbers can be accurately represented in base 10, not all numbers can be accurately represented in base 2 either.
For example, "1/3" may be written in base 10 as 0.33333 or 0.33334. Neither is really "correct"; they're just the best we can do. A "DOUBLE" in base 10 might be 0.3333333333 or 0.3333333334, which is double the digits, yet still not "correct".
The best options are to either use a DECIMAL value, or use an INT value (and multiply your actual values by, say, 10000 or 100000 in order to get the decimal digits you care about into that int).
The DOUBLE type represent only approximate numeric data values. Try to use the DECIMAL type.
Is your column floating point? Calling microtime with true gives you a float, and that looks like a float, which will have digits after the .51878 that you don't see, so those digits make the stored value greater than the value you have in your query.
Unless you really need the float I'd convert the string result to an int, or even two columns for seconds and useconds. Then you can use > or < on known values without worrying about the imprecision of the floating point value.
I need to round any non-integers up to the nearest integer, regardless of whether the number after the decimal place is >5 or not.
You can make use of the ceil($value) function in PHP to round up.
Similarly you can make use of floor() for rounding down.