In essence it's how decimal fractions are represented in binary
in binary
.1 is a half .01 is a quarter .001 is an eighth and so on.
The binary representation of decimal .1 is not an exact value...
.0001 = 0.0625 .00011 = .09375 .000110011 = .099609375 .0001100110011 = .0999755859375
As you can see it is a recurring number that will approximate to .1 (.01 is a similar value, try it for yourself) So a computer, which works in binary can only get an approximation to the decimal number .1. Whilst PHP has checks built in to locate this error there are ways to circumvent these checks, or at least make it harder for PHP to spot the errors that do creep in. My solution was to increment the loop by .001, the extra level of significant digits triggers off sufficient error checking, your specific call to the round function also triggers of extra error checking.
I hope that helps,
graeme
JC Botha wrote:
Hi Jin,
Yes that also buged me, had no idea why it does that. I also battled with this one for a while. Perhaps there are more on the mailing list that got some info on this technical point.
Thanks for your intrest!
Chris
On 4/21/05, Wu, Jin Yong <jinyong.wu@xxxxxxxxxxxxx> wrote:
It's so interesting. At the beginning, I missed the statement "$x = round($x, 2) + 0.01;", and can't get corrent answer.Then, I trace the $x value, I found its value was changed to have 13 decimal places from 4.43 on. Could you explain it for me?thank you ahead.
-----Original Message----- From: JC Botha [mailto:odegos@xxxxxxxxx] Sent: Wednesday, April 20, 2005 19:50 PM To: graeme Cc: php-windows@xxxxxxxxxxxxx Subject: Re: Re: Jaw Breaker - What's the ansewer?
Well done Graeme!
Posted below is what I used to generate the asnwer, I myself had dificulty to get it. Let me know if you used another method.
The Source Code ================================================== <?php function f($c) { $c++; if ($c % 2) { return f($c); } return $c++; }
function g($n) { for ($i=1;$i<10;$i++) { $n = f($n*$i); } return ($n); } $x = 0.00; while ($x < 10){
$x = round($x, 2) + 0.01; $l = (g($x));
if ($l == 4277108){ echo("<font color='red'>:: x = $x : $l</font> <br/>"); } //echo ("> $x : $l<br/>");
}
?>
=================================================
On 4/20/05, graeme <graeme_foster@xxxxxxxxxxxxxxxx> wrote:
Yes it is an issue with floating point numbers since:
8.35 will give the answer but if you increment by .01 in a loop then you will not get the answer, when it is on 8.35. However, increment by 0.001 then 8.35 will provide the correct answer. It's all to do with how in calculates 0.01 in binary, a rational fraction in binary.
graeme.
JC Botha wrote:
It is possible, and "10.642868165785" is incorrect. The question says "$x is a number between 1 and 10 and has 2 decimal places."
Try again, if more try then I will post the source code that generates the asnwer?
On 4/20/05, M. Sokolewicz <tularis@xxxxxxx> wrote:
JC Botha wrote:
The following is a section of PHP code (see Apache.org and PHP.net).
function f($c) { $c++; if ($c % 2) { return f($c); } return $c++; }
function g($n) { for ($i=1;$i<10;$i++) { $n = f($n*$i); } return ($n); }
print(g($x));
What is the smallest value that $x can have if 4277108 is outputted to the screen after running this code? $x is a number between 1 and 10 and has 2 decimal places.
it's not a jawbreaker, it's impossible IMO. f() always returns the number if it's uneven, or if it's even, it returns (n+1). So, it always returns uneven. which means the result of g() can *never* be even.
[[side note: unless "return $c++;" does first add 1 to it before returning, but I think it doesn't, since it's a postincrement operator. ]]
-- PHP Windows Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
-- Experience is a good teacher, but she sends in terrific bills.
Minna Antrim
-- PHP Windows Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
-- Experience is a good teacher, but she sends in terrific bills.
Minna Antrim