Do you have a question? Post it now! No Registration Necessary. Now with pictures!
- Subject
- Posted on
posted on
October 26, 2009, 7:49 am
October 26, 2009, 7:49 am
Hi guys, i have to ask you 10 seconds of your time ;)
Me and other from the it.comp.www.php group have found a strange
behavior of number_format() function, and we dont know if it depends
on the php version installed, math libs, or whatever.
Please, run this simple code and watch the output:
--------------------------
$a = 0.715;
$b = 0.615;
$a_r_up = 0;
$a_r_down = 0;
$b_r_up = 0;
$b_r_down = 0;
for($i = 0; $i < 1000; $i++){
$ia = number_format($i + $a, 2);
$ib = number_format($i + $b, 2);
list($a_int, $a_dec) = explode('.', $ia);
$a_dec == 72 ? $a_r_up++ : $a_r_down++;
list($b_int, $b_dec) = explode('.', $ib);
$b_dec == 62 ? $b_r_up++ : $b_r_down++;
}
echo $a . ' rounded UP: ' . $a_r_up . ', rounded DOWN: ' . $a_r_down .
'<br />';
echo $b . ' rounded UP: ' . $b_r_up . ', rounded DOWN: ' . $b_r_down;
--------------------------
In my case, for example, the output is:
0.715 rounded UP: 929, rounded DOWN: 71
0.615 rounded UP: 978, rounded DOWN: 22
How is possible that for some integer, number_format round the decimal
part (0.x15), and for some other it round it down?
For 0.715, it round down just when the integer part is between 256 and
326 (in my case).
Tested on: Win2003 IIS6, Linux Debian apache2, Linux Ubuntu 9.04
apache2, in all cases is php5.
Re: Strange problem with number_format() function, please need your help.
<snip example>
This is the nature of floating point numbers. Many decimal fractions cannot
be represented exactly in a binary floating point number, just as 1/3 cannot
be represented exactly in base 10, although it *can* be represented exactly
in base three (1/3 = 0.1, 2/3 = 0.2, 3/3 = 1.0). This is not limited to any
particular "version of PHP" but is a feature of the hardware and affects
every single floating point number in any language on any machine.
Google for floating point fractions.
Irrelevant, see above.
Re: Strange problem with number_format() function, please need your help.
rf wrote:
Not quite true. For instance, COBOL on IBM mainframes can use packed
decimal, which does represent decimal numbers exactly (hardware
supported). And the bcd library in PHP can also represent it exactly
(software supported).
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================
Re: Strange problem with number_format() function, please need your help.
But the problem here is not the float operation, but the number_format
() output.
Dumping the addittion, will result as the exact floating value (X.
715);
After number_format, comes the trouble (X.7149999999999999999999)..
I solved this writing my own number_format function.
I dont need the bc library in this case becose i wont use more than 4
decimals
Re: Strange problem with number_format() function, please need your help.
Next time you post here please quote a bit of the previous conversation so
we can see exactly what you are answering. And in this case you are actually
answering the wrong post, a not uncommon problem for someone using the
dreaded google groups broken usenet interface.
Are you sure of this? I am not.
Did you read and understand any of the links you found in the google search
I suggested? The operative thing is that floating point numbers are
normalised. It does not matter that you think you have something before the
"decimal point" and something after it. When your number is converted to
floating point and stuffed into a floating point register things change
dramatically. Floating point numbers are *not* exact, well mostly.
Would you care to share this code with us?
What bc library?
In any case this is most definately not a PHP issue.
Re: Strange problem with number_format() function, please need your help.
That's the point.
Wroted in 5 mins, still need work:
function my_number_format($num, $dec = 2, $dec_sep = ',', $thu_dec =
'.'){
if(strstr($num, '.')){
list($intero, $decimali) = explode('.', (string)$num);
}else{
$intero = $num;
$decimali = 0;
}
$nDec = strlen($decimali);
$decCut = substr($decimali, 0, $dec);
if($nDec > $dec){
$lastDec = $decimali[$dec];
if($lastDec >=3D 5){
$decCut++;
}
}
if(strlen($decCut) > $dec){
$intero++;
$decCut = '';
for($i=3D0; $i !=3D $dec; $i++){
$decCut .=3D '0';
}
}
while(strlen($decCut) < $dec){
$decCut = $decCut . '0';
}
$interoS = number_format($intero, 0, '', $thu_dec);
if($dec =3D 0){
return $interoS;
}else{
return $interoS . $dec_sep . $decCut;
}
}
Simply, i treat the decimals as integers, cut the number of digits
after the zero, if the last digit usefull is >=3D 5 increment it, else
not.
Then 'rebuild together' the number, as a float.
http://uk.php.net/manual/en/ref.bc.php
Who cares if the problem is about php itself or the hardware running
it, or whatever?
I have that:
270 + 0.715 = 270.71 <-
and
215 + 0.715 = 215.72 <-
And need to solve this situation ;)
Re: Strange problem with number_format() function, please need your help.
Binary floating point cannot represent X.715 with less than an
infinite number of bits. (If a number has two or more digits after
the decimal point, there's no exact representation of it in binary
floating point unless those digits are 25 or 75, disregarding
trailing zeroes.)
If you're getting it printed as X.715, you're not printing it with
enough digits.
*Decimal* floating point does not have this problem, but few machines
have decimal floating point hardware.
2.715 as long double:
Before:
2.71499999999999999970509700908394279394997283816337585449218750000000000000000000
Value:
2.71499999999999999992193744358104368075146339833736419677734375000000000000000000
After:
2.71500000000000000013877787807814456755295395851135253906250000000000000000000000
2.715 as double:
Before: 2.714999999999999413802242997917346656322479248046875000000000
Value: 2.714999999999999857891452847979962825775146484375000000000000
After: 2.715000000000000301980662698042578995227813720703125000000000
2.715 as float:
Before: 2.714999675750732421875000000000000000000000000000000000000000
Value: 2.714999914169311523437500000000000000000000000000000000000000
After: 2.715000152587890625000000000000000000000000000000000000000000
Re: Strange problem with number_format() function, please need your help.
This is the nature of *binary* floating point numbers. Decimal
floating point (yes, there is such a thing) doesn't have this
problem. However, very few machines (especially the ones in common
use) have decimal floating point hardware. Decimal floating point
software is a little bit more common.
Nitpick: *binary* floating point number.
Site Timeline
- » Call back function
- — Next thread in » PHP Scripting Forum
- » Help with IF statement behaviour
- — Previous thread in » PHP Scripting Forum
- » URL redirection
- — Newest thread in » PHP Scripting Forum
- » Seamless SSO
- — Last Updated thread in » PHP Scripting Forum
- » Dell Battery Slice LED codes
- — The site's Newest Thread. Posted in » Laptop Computers Forum