ホームページ  >  記事  >  バックエンド開発  >  PHP 浮動小数点数の知識_PHP チュートリアル

PHP 浮動小数点数の知識_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-13 09:53:51817ブラウズ

PHP浮動小数点数の知識

この記事では主にPHP浮動小数点数について知っておくべき知識を紹介します。 この記事では、PHP浮動小数点数、PHP数値の重要な値、精度の損失などについて説明します。参考にしてみてください

PHP は弱い型指定言語であり、そのような機能では必然的にシームレスで透過的な暗黙的な型変換が必要になります。PHP は内部で zval を使用して、任意の型の値を格納します (例として 5.2)。

コードは以下の通りです:

struct _zval_struct {

/* 可変情報 */

zvalue_value 値 /* 値 */

zend_uint refcount;

zend_uchar 型; /* アクティブ型 */

zend_uchar is_ref;

};

上記の構造で、実際に値そのものを格納するのは zvalue_value ユニオンです:

コードは以下の通りです:

typedef Union _zvalue_value {

long lval /* 長い値 */

double dval /* double 値 */

構造体{

Char *val;

int len;

}str;

HashTable *ht; /* ハッシュテーブル値 */

zend_object_value obj;

} zvalue_value;

今日のトピックでは、そのうちの 2 つ、lval と dval にのみ焦点を当てます。long lval はコンパイラと OS のワード長に応じて不確実な長さを持ち、Double dval (倍精度) であることを認識する必要があります。 IEEE 754 によって指定されており、固定長であり、64 ビットである必要があります。

これにより、一部の PHP コードは「プラットフォームに依存しない」ものになるため、以下の説明では、特に指定がない限り、long が 64 ビットであることを前提としています。

ここでは IEEE 754 の浮動小数点カウント方法を引用しません。興味があれば、ご自身で確認してください。重要な点は、二重仮数が 1 つの隠れた有効ビットをカウントすることです。合計は 53 ビットです。

ここで、非常に興味深い疑問が生じます。例として C コードを使用してみましょう (long が 64 ビットであると仮定します)。

コードは以下の通りです:

long a = x;

assert(a == (long)(double)a);

すみません、a の値がどの範囲内にある場合、上記のコードは成功すると言えますか? (答えは記事の最後に残しておきます)

それでは、本題に戻りましょう。PHP は、スクリプトを実行する前に、まずスクリプトを読み取り、スクリプトを分析する必要があります。たとえば、次のスクリプトの場合は、次のとおりです。

コードは以下の通りです:

$a = 9223372036854775807; //64ビット符号付き数値の最大値

$b = 9223372036854775808; //最大値+1

;

var_dump($a);

var_dump($b);

出力:

コードは以下の通りです:

int(9223372036854775807)

float(9.22337203685E+18)

つまり、字句解析の段階で、PHPはリテラル値が現在のシステムの長いテーブル値の範囲を超えているかどうかを判断し、超えていない場合はlvalを使用して保存し、それ以外の場合はzvalを使用します。 dval は、zval IS_FLOAT を意味します。

精度が失われる可能性があるため、最大の整数値より大きい値には注意する必要があります。

コードは以下の通りです:

$a = 9223372036854775807;

$b = 9223372036854775808;

var_dump($a === ($b - 1));

出力は false です。

冒頭の議論の続きですが、前述したように、PHP の整数は 32 ビットまたは 64 ビットの場合があるため、64 ビットで正常に実行できる一部のコードは、目に見えない型変換、精度の影響を受ける可能性があると判断されます。損失が発生し、コードが 32 ビット システムで適切に実行されなくなります。

したがって、この重要な値には注意する必要があります。幸いなことに、この重要な値は PHP で定義されています。

コードは以下の通りです:

エコー PHP_INT_MAX;

?>

もちろん、安全のために、大きな整数を格納するには文字列を使用し、計算を実行するにはbcmathなどの数学関数ライブラリを使用する必要があります。

さらに、私たちを混乱させるもう 1 つの重要な設定があります。この設定は php.precision です。この設定は、PHP が float 値を出力するときに出力する有効桁数を決定します。

最後に、上で挙げた質問を振り返ってみましょう。つまり、float に変換してから long に戻すときに精度の低下がないよう、long 整数の最大値はいくらですか?

たとえば、整数の場合、そのバイナリ表現は 101 であることがわかっています。次に、2 ビットを右シフトして 1.01 にし、上位の暗黙的な有効ビット 1 を破棄して、バイナリ値 5 を取得します。二重に:

コードは以下の通りです:

0/*符号ビット*/ 10000000001/*指数ビット*/ 01000000000000000000000000000000000000000000000000

5のバイナリ表現は、損失なく仮数部に格納されます。この場合、doubleからlongに変換するときに精度が失われることはありません。

double は仮数を表すために 52 ビットを使用することがわかっています。暗黙の最初の 1 を数えると、合計は 53 ビットの精度になります。したがって、long 整数の値が次の値より小さいと結論付けることができます。

コードは以下の通りです:

2^53 - 1 == 9007199254740991; //ここでは 64 ビット長であると仮定していることに注意してください

そうすると、この整数は、long->double->long 値の変換が発生したときに精度が失われることはありません

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/1000081.html技術記事 PHP 浮動小数点数の知識 この記事では、PHP 浮動小数点数について知っておくべき知識を主に紹介し、PHP 浮動小数点数、PHP 数値の重要な値、精度の損失などについて説明します。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。