3

これは以前に出てきたと思いますが、質問に対する答えが見つかりませんでした。ここに小さなコードスニペットがあります:

    $stmt = $this -> db -> query("
        SELECT
          `Field`
        FROM
          `Table`
        WHERE
          (`ID` = 33608)");
    var_dump($stmt -> fetch());

そして、これは私が得る結果です:

    array(1) { ["Field"]=> float(1.7999999523163) }

ただし、MySQL データベースのデータは 1.8 です。フィールドの型は float(7,4) です。$this->db は PDO オブジェクトです。私は最近 (AdoDB から) PDO に移行しましたが、このコードは以前は正常に動作していました。ここで何がうまくいかなかったのかわかりません。正しい方向に私を向けることができますか?ありがとう!

4

2 に答える 2

4

Floating-Point Types (Approximate Value) - のFLOATDOUBLE下に記載されているよう:

MySQL は値を格納するときに丸めを行うため、列に挿入999.00009するFLOAT(7,4)と、おおよその結果は になり999.0001ます。

浮動小数点値は近似値であり、正確な値として格納されないため、比較で正確な値として処理しようとすると問題が発生する可能性があります。また、プラットフォームまたは実装の依存関係にも左右されます。詳細については、セクションC.5.5.8「浮動小数点値の問題」を参照してください</a>

移植性を最大限に高めるために、おおよその数値データ値の格納を必要とするコードでは、精度や桁数を指定せずにFLOATorを使用する必要があります。DOUBLE PRECISION

したがって、1.8データベースへの挿入時に、MySQL はリテラルを に丸め、その数値に001.8000最も近い近似値をbinary32形式でエンコードします。つまり0x3FE66666、そのビットは次を意味します。

サイン           :0b0

偏った指数: 0b01111111
               = 127 (表現には +127 のバイアスが含まれているため、exp = 0)

    仮数 : 0b[1.] 11001100110011001100110
                    ^ バイナリ表現で格納されていない隠しビット
               = [1.]7999999523162841796875

これは次のようになります。

(-1)^ 0 * 1.7999999523162841796875 * 2^ 0 
=          1.7999999523162841796875

これは、MySQL からクライアントに返される値です。その後、AdoDB は列のデータ型を検査し、それに応じて結果を丸めたように見えますが、PDO はそうではありません。

正確な値が必要な場合は、 などの固定小数点データ型DECIMALを使用する必要があります。

于 2013-06-11T15:59:12.890 に答える
1

正確な値が必要な場合は、DECIMAL代わりにフィールド タイプを使用する必要があります。 そして、PDOはそれとは何の関係もありません。それはむしろ、コンピューターが一般的にどのように機能するかに関係しています。FLOAT

于 2013-06-11T15:38:13.737 に答える