質問掲示板

CGIなどのの質問を受付ます。
現在SPAM対策の為、一部ホストアドレスを規制中。

新規発言一覧最新記事過去一覧 | 検索HOME

スレッド

└◇96:
なんでやねーん!(PHPバグ?) [moon] 12/12 20:06

 └◇97:Re:なんでやねーん!(PHPバグ?) [とむ] 12/17
  ├◇98:Re[2]:なんでやねーん!(PHPバグ?) [とむ] 12/17
  └◇99:Re[2]:なんでやねーん!(PHPバグ?) [あ---、] 12/17
   └◇100:さんきゅー [moon] 12/17 <


96● なんでやねーん!(PHPバグ?)[ moon ] 2003 12/12 20:06
以下のコードを走らせて見よう。

for ($i=0.995;$i<1.005;$i+=0.001) {
    echo "$i ";
    echo intval($i);
    echo "<br>";
}

echo "<br>";

for ($i=0.95;$i<1.05;$i+=0.01) {
    echo "$i ";
    echo intval($i);
    echo "<br>";
}

echo "<br>";

for ($i=0.5;$i<1.5;$i+=0.1) {
    echo "$i ";
    echo intval($i);
    echo "<br>";
}

----結果----

0.995 0
0.996 0
0.997 0
0.998 0
0.999 0
1 1
1.001 1
1.002 1
1.003 1
1.004 1
1.005 1

0.95 0
0.96 0
0.97 0
0.98 0
0.99 0
1 1
1.01 1
1.02 1
1.03 1
1.04 1

0.5 0
0.6 0
0.7 0
0.8 0
0.9 0
1 0
1.1 1
1.2 1
1.3 1
1.4 1


...
なんで下一桁だけだと 1 で intval(1) とすると 0 になる!?
つか、上の 1 はどれも同じだと思うのですが。。。
なんでじゃー??
スレッド一覧


97● Re:なんでやねーん!(PHPバグ?)[ とむ ] 2003 12/17 00:31
ほほ〜。おもろいなぁ。なんでやねん。
確かに0.1のオーダーではintval($i)=0やなぁ。

$i = 1.0;
intval($i)
とすると、1となるのでバグの可能性が大きなぁ

場合によっては、ビット演算による誤差の可能性も捨てきれないけど、
Cよりは判定厳しくないはずだから・・・
取り合えず、0.1のオーダーでintvalかけるときはこっそりと0.01足しとけ。
スレッド一覧


98● Re[2]:なんでやねーん!(PHPバグ?)[ とむ ] 2003 12/17 00:55
うぃ、忘れてた。

一応、0.5〜3.5までの範囲で同じループかけた結果、1.0のみが変なことが判明。
一応ソースと結果。

for ($i=0.5;$i<3.5;$i+=0.1) {
echo "$i ";
echo intval($i);
echo "<br>";
}

----------------------------------------

0.5 0
0.6 0
0.7 0
0.8 0
0.9 0
1 0
1.1 1
1.2 1
1.3 1
1.4 1
1.5 1
1.6 1
1.7 1
1.8 1
1.9 1
2 2
2.1 2
2.2 2
2.3 2
2.4 2
2.5 2
2.6 2
2.7 2
2.8 2
2.9 2
3 3
3.1 3
3.2 3
3.3 3
3.4 3
スレッド一覧


99● Re[2]:なんでやねーん!(PHPバグ?)[ あ---、なる。わかった。 ] 2003 12/17 01:18
for ($i=0.5;$i<1.0;$i+=0.1) {
echo "$i ";
echo intval($i);
echo "<br>";
}
if($i == 1.0){ print 'マチュピチュ!!'; }

のループ試してわかったんだけど、
多分0.01を100回足しても1にならない(倍精度浮遊少数の場合)
と同じ現象のような気がする。
いわゆる、ビットによる計算誤差ね。

0.01以下のオーダーと
0.1でのオーダーでビット数が違うため(変数タイプが違う)
に計算結果が変ったものと推定。
まあPHP,PERLではPGが意識的に変数定義しないからねぇ。

[上のループの結果]
0.5 0
0.6 0
0.7 0
0.8 0
0.9 0
1 0

マチュピチュ!!は表示されず。
スレッド一覧


100● さんきゅー[ moon ] 2003 12/17 23:55
なんか、話が難しいところに行ってしまった(汗

まぁ、型が弱いPGの弱点といったところか。
別にほかにやりようがあるからいいけどね。

// 浮動小数点数を含む全ての配列要素を返す
$fl_array = preg_grep ("/^(\d+)?\.\d+$/", $array); // preg_match でもいい。どちらにしろ強引だが。
とか
$four = floor(4.3); // round はビミョウに違うか。

perlと同じようにやると int = intval になるからってだけで使っただけですが。
スレッド一覧

CGIROOM