2011-01-05 8 views
4

浮動小数点数に関するPHPの興味深い記事を読みました。The RegisterExploring Binaryを参照してください。PHP浮動小数点型のバグ:PHPが数値でハングアップする

浮動小数点を明示的に使用することは一切ありません。私はnumber_format()を使用して入力を消去し、例として価格を表示します。

また、私が知っている限り、例のフォームからのすべての入力は、私がそうでないと言うまで文字列であるので、この問題が私に影響しないと仮定しています。

私はそうですか、または私のサーバー上のWordpressとSquirrelmailのインストールをチェックして、何かフロートするかどうか確認する必要がありますか?または、より良い、grepfloatのために私のサーバー上のすべてのPHPファイル?

+2

*(参考)* http://bugs.php.net/bug.php?id=53632 – Gordon

答えて

5

つの方法の問題を軽減する:

  1. 現代のCPUを使用してください。現代の64ビットCPUのほとんどは免責されています(現代的なハードウェアを使用する傾向があるため、実際にはホストを見つけることができません)。 Amazon VMも免疫力があるようです。
  2. PHPバージョン5.3.5および5.2.17をリリースしたばかり(おそらく本日)に修正が含まれています。
  3. CFLAGSで-ffloat-storeでビルドしてください(コードが遅くなります)。
  4. patchをコードに手動で適用し、PHPを再構築します。 zend_strtodとして役立つことはありません、おそらくfloatを持っているコードを探してい

は、多くのstring->番号変換シナリオでエンジンによって使用されています。

P.S.このコードは標準BSDライブラリstrtodのコードであり、PHP固有のものではありません。このコードを使用する他のプロジェクトも影響を受ける可能性があります。

+0

ありがとうございますが、私は実際に64ビットではない古いサーバを1台使用していますが、マイグレーションは大変な作業になります。既にdo-doリスト... – jeroen

+0

@jeroen:このパッチを適用することができます:http://svn.php.net/viewvc/php/php-src/branches/PHP_5_2/Zend/zend_strtod.c?r1=266327&r2= 307095&view = patch – StasM

4

hackernewsより:

この問題は、IA-32の 80ビット浮動小数点演算に生じます。 シンプルな修正: "-ffloat-store"フラグ をCFLAGSに追加してください。

問題機能、zend_strtod、 仮数(2.225 ... 011部)を解析すると思われると 指数(-308部)Mの近似alculate別々に、 C> * 10^E とエラーが ,0.5ulp未満になるまで、それを逐次的に改善してください( )。問題は、 のこの特定の数値は、 の80ビットFPでは無限ループ の無限ループ(つまり、反復では はエラーを改善しません)を引き起こしますが、64ビットFPでは発生しません。 一般的に、x86-64では廃止予定のx87の代わりに 命令セット(64ビットFPあり) を使用しているため、 にはこの問題はありません。

+0

実際、神経質になる前にアーチをチェックしてください。影響を受ける場合は、プロバイダに変更を依頼して更新してください。入力配列をスキャンするのが最後の手段です。 – mario

+0

@marcogありがとうございます。しかし、問題は、*シンプルな修正が私にはアブラカダブラのようなものです... – jeroen

+0

@jeroen '-ffloat-store'はCコンパイラのフラグです。それを使ってPHPを再コンパイルしてください。 – marcog

1

明示的な浮動小数点型の検索はあなたを助けません - phpでは、変数はそれが使われているものとして扱われます。小さな例:

$mystring = "123.45"; //mystring is a string here 
$myvalue = $mystring * 4; // mystring is a float here 
          // and there's no explicit float-cast 

あなたが見ることができます:あなたのPHPインストールをアップグレード/修正することは、デッドサーバーを避ける唯一の保存方法です。

EDIT:あなたのコメントへの

山車は本当に簡単ということarn't。 0.7や0.8のような単純な数値でも正確に保存することができないので、0.8を計算した後、0.799999999789になる可能性があります...さらに問題が発生するまでは時間がかかるだけです。単なる一例として

(とは、Windowsユーザーなら):

  1. 窓-電卓を開く
  2. substract(2でなければなりません)4のsqareルートを計算2結果から(0にする必要がありますが... woooow;))

このバグはWindows-calculator以来です。これは、浮動小数点を使用しても大きなコンパニオンでも失敗する可能性があることを示しています。このようなバグがあれば、となります(このPHPバグのように)にアップグレード/それを修正し、棒なし。

+0

ありがとうございますが、それはもちろんですが、すべての変数が 'ints'や' strings'で最大2〜4小数の浮動小数点型として解釈できるならば、それは問題ではありません。 – jeroen

+0

@jeron:私の編集を見てください、それはコメントのためには長すぎました;) – oezi

+0

私は間違いなく問題を解決するつもりです、そして、私は '浮き沈み'の問題を一般的に知っていますが、これまでのところ、単純な計算がその魔法の数につながる可能性は非常に低いと思われるので、それは非常に緊急ではないようです(私は価格、為替レートなどを話しています)。 – jeroen

1

変数値を浮動小数点に明示的にキャストするコードを検索するだけでは不十分ですが、キャストが暗黙的に存在するインスタンスは見つかりません。

$d = '2.2250738585072011e-308'; 
$f = float($d); 

は、明示的なキャストですが、何のようなコードについて:

$d = '2.2250738585072011e-308'; 
$f = $d + 0.1; 

または

$d = '2.2250738585072011e-308'; 
if ($d == 0.5) { 

私はこのバグも今も、最新のPHPのビルド・コード内に固定されていることを信じていますxamppなどのパッケージは引き続き影響を受けます。

+0

ありがとう、しかし、私は@ oeziの答えにコメントしたので、それは問題ではありません。 – jeroen

2

marcog氏によると、それはx87計算の浮動小数点算術バグです。あなたは、GCCのバグをチェックアウトLink

+0

浮動小数点数学の落とし穴に関する面白い論文http://hal.archives-ouvertes.fr/hal-00128124 – Kyle

3

として迅速な回避策をそれについての詳細を読みたい場合は、入力配列をスキャンできます。

foreach(array("_GET","_POST","_REQUEST","_COOKIES") as $G) { 
    if (in_array('2.2250738585072011e-308', $$G)) { 
     header("Status: 422 Unprocessable Entity"); 
     exit; 
    } 
} 

あなたがサブアレイを使用しない場合、これは、十分です入力変数。これは、浮動小数点を文字列として保持し、入力配列が文字列を保持し、in_arrayも文字列コンテキストで動作するために機能します。

しかし、私はその価値の他の表現があるかどうかは考えていません。これはこれまでに働くことが知られている唯一のものですが、それ以上のものもあります。だから、更新することをお勧めします:|

+2

「Exploring Binary」によれば、同じ数の異なる形にはすべて問題があります。 – jeroen

+1

異なるフォームは、おそらく '2.22507385850'のように同じプレフィックスで始まるでしょう – StasM

関連する問題