ホームページ >バックエンド開発 >PHPチュートリアル >PHP浮動小数点数の使い方と問題点まとめ_PHPチュートリアル

PHP浮動小数点数の使い方と問題点まとめ_PHPチュートリアル

WBOY
WBOYオリジナル
2016-07-13 10:49:30819ブラウズ

PHPにはceil、floor、round、intvalなどの浮動小数点数処理関数がたくさんありますが、それらで処理した後、浮動小数点数に必要な小数点以下の桁数を返すことができます。その使い方と問題点をいくつか紹介します。 PHP での浮動小数点数の解析。

1、PHP浮動小数点数の使い方

PHP浮動小数点型丸め上限 — さらなる丸め方法
説明
float ceil (浮動小数点値)
value より小さくない次の整数を返します。 value に小数部分がある場合は切り上げられます。通常、浮動小数点値の範囲は整数の範囲よりも大きいため、ceil() によって返される型は依然として浮動小数点です。

例 1. ceil() の例

コードは次のとおりです コードをコピー

エコー ceil(4.3) // 5
; エコー ceil(9.999) // 10
; ?>

PHP浮動小数点型丸め床 - 丸めメソッドによる丸め

手順
float フロア (float 値)
value 以下の次の整数を返します。value の小数部分は四捨五入されます。通常、float 値の範囲は integer の範囲よりも大きいため、floor() によって返される型は float のままです。

例 1.floor() の例

コードは次のとおりです コードをコピー

エコーフロア(4.3) // 4
; エコーフロア(9.999) // 9
; ?>

PHP 浮動小数点型の丸め — 浮動小数点数の丸め
説明
float ラウンド ( float val [, int precision] )
指定された精度 (小数点以下の小数点以下の桁数) に丸められた val を返します。精度は負またはゼロ (デフォルト) にすることもできます。

例 1.round() の例

コードは次のとおりです コードをコピー


< ?php
エコーラウンド(3.4) // 3
; エコーラウンド(3.5) // 4
; エコーラウンド(3.6) // 4
; エコーラウンド(3.6, 0) // 4
; エコーラウンド(1.95583, 2); // 1.96
; エコーラウンド(1241757, -3); // 1242000
エコーラウンド(5.045, 2) // 5.05
; エコーラウンド(5.055, 2) // 5.06
; ?>

PHP 浮動小数点型の丸め間隔 - 変数を整数型に変換します
例 intval()

コードは次のとおりです コードをコピー
エコー間隔(4.3) //4
; echo intval(4.6); // 4
; ?>

2番目に、浮動小数点数を文字列に変換します

PHP の組み込みの echo、var_dump、json_encode、文字列のスプライシング、およびその他の関数 (命令) では、浮動小数点数を表示するときに問題が発生し、精度が失われます。

コードは次のとおりです コードをコピー

$a = 1315537636.338467;

printf("%f", $a); echo "n";

echo $a . "n";

echo $a;

?>

結果

1315537636.338467

1315537636.3385

1315537636.3385

言い換えれば、浮動小数点数を文字列に変換したり表示したりするために、PHP の最も便利な方法を使用することはできません。浮動小数点数を文字列に変換するには、printf/sprintf を使用する必要があります。


3、よくある質問への答え

しかし、私はその時、次のよくある質問に対する答えを 1 つ見逃していました:

コードは次のとおりですコードをコピー出力が 57 になるのはなぜですか
$f = 0.58; var_dump(intval($f * 100)); ?>


出力が 57 になるのはなぜですか? PHP のバグですか?

bugs.php.net でよく質問されることは言うまでもなく、同様の質問をする人がたくさんいるので、多くの学生がこの質問を抱いたことがあると思います...

この理由を理解するには、まず浮動小数点数の表現 (IEEE 754) を知る必要があります:

浮動小数点数は、64 ビット長 (倍精度) を例として、1 つの符号ビット (E)、11 の指数ビット (Q)、および 52 ビットの仮数ビット (M) で表されます (合計 64 ビット)。 .

符号ビット: 最上位ビットはデータの符号を表し、0 は正の数を表し、1 は負の数を表します。

指数ビット: データの累乗を基数 2 で表し、指数はオフセット コードで表されます

仮数: データの小数点以下の有効数字を示します。

ここで重要なのは、バイナリでの小数を表現する方法については、ここでは詳しく説明しません。0.58 は無限に長いということです。バイナリ表現 (以下の数字は暗黙の 1 を省略します)..

0.58 のバイナリ表現は基本的に (52 ビット) です:

0010100011110101110000101000111101011100001010001111

0.57 のバイナリ表現は基本的に (52 ビット) です: 0010001111010111000010100011110101110000101000111101

これら 52 ビットのみを使用して 2 つの 2 進数を計算すると、次のようになります。
0.58 -> 0.57999999999999996
0.57 -> 0.56999999999999995


具体的な浮動小数点の乗算0.58 * 100については、詳しくは考えませんので、興味のある方は暗算で見てみてください... 0.58 * 100 = 57.999999999

それでは、計算すると自然に57になります…

この問題の重要なポイントは、「一見有限に見える 10 進数は、コンピューターの 2 進数表現では実際には無限である」ということです。

四、float(浮動小数点数)の比較問題

最近、契約管理システムを開発していたとき、2つの浮動小数点数を比較する作業があり、とても落ち込んでいました。 昔、「浮動小数点数の比較には等号を使うな」という「真実」をどこで聞いたのか、常用していましたが、今回は問題なかったように思えます。問題はついにやって来ました。


コードは次のとおりですコードをコピー $sum = "12300.00"; $a = "10000.30"; $b = "2000.30"; $c = "299.40"; コードをコピー
$sum = (浮動小数点) $sum

; $s = (浮動小数点) ($a+$b+$c); var_dump($sum, $s); var_dump($sum==$s);




結果は次のとおりです:



コードは次のとおりです

フロート(12300) フロート(12300)

後で知ったのですが、PHP では 2 つの浮動小数点数の大きさを比較するには、bccomp (パラメーター 1、パラメーター 2、小数点以下の桁数) を使用して比較できます。

ブール(偽)
コードは次のとおりです コードをコピー

$sum = "12300.00"; $a = "10000.30"; $b = "2000.30"; $c = "299.40";
$sum = (浮動小数点) $sum
; $s = (浮動小数点) ($a+$b+$c); var_dump($sum, $s); var_dump(bccomp($sum,$s,2));

結果:

フロート(12300)
フロート(12300)
int(0) // 0 は 2 つの浮動小数点値が等しいことを意味します


bccomp関数の具体的な使い方については、PHPマニュアルを参照してください

http://www.bkjia.com/PHPjc/632704.htmlwww.bkjia.com

tru​​e

技術記事 PHP には、ceil、floor、round、intval など、浮動小数点数を処理する関数がたくさんあります。これらの関数を処理した後、浮動小数点数に必要な小数点以下の桁数を返すことができます。その 1 つを紹介しましょう。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。