2

私は PHP の ceil() 関数と格闘しており、結果が少し間違っています。次の点を考慮してください。

$num = 2.7*3; //float(8.1)
$num*=10; //float(81)
$num = ceil($num); //82, but shouldn't this be 81??
$num/=10; //float(8.2)

小数点以下の桁数が任意の数値があり、小数点以下 1 桁に切り上げる必要があります。つまり、8.1 は 8.1、8.154 は 8.2、8 は 8 のままにする必要があります。

私がそこにたどり着く方法は、数値を取り、10 を掛け、それを ceil() してから 10 で割ることですが、ご覧のとおり、状況によっては余分な .1 が追加されています。

なぜこれが起こっているのか、それを修正する方法を教えてもらえますか?

どんな助けでも大歓迎です

編集: *=10 の代わりに +=10 がありました:S

EDIT 2:これについては明示的に言及しませんでしたが、常に切り上げ、決して切り下げるには小数点が必要です-この答えはこれまでのところ最も近いです:

rtrim(rtrim(sprintf('%.1f', $num), '0'), '.');

ただし、3.9 が必要な場合は、3.84 を 3.8 に丸めます。申し訳ありませんが、これは明確ではありませんでした:(

最終編集:

私がやったことはこれでした:

$num = 2.7*3; //float(8.1)
$num*=10; //float(81)
$num = ceil(round($num, 2)); //81 :)
$num/=10; //float(8.1)

どちらが機能します:)

4

6 に答える 6

2

これは、浮動小数点エラーが原因である可能性が高いです。

代わりに、この手順を試してみてください。

<?php
$num = 2.7*3;
echo rtrim(rtrim(sprintf('%.1f', $num), '0'), '.');
于 2011-10-19T17:26:35.790 に答える
2

フロートは気まぐれなものになる可能性があります。すべての実数を有限数のバイナリ ビットで適切に表現できるわけではありません。
結局のところ、0.7 の小数部分はそれらの数値の 1 つです (0.10 の後に "1100" を繰り返す無限大が続きます)。最終的には 0.7 をわずかに上回る数値になるため、10 を掛けると 1 の桁は 7 をわずかに上回ることになります。

あなたができることは、健全性チェックを行うことです。浮動小数点数を取り、整数形式を減算します。結果の値が 0.0001 より小さい場合は、内部の丸め誤差と見なし、そのままにしておきます。結果が 0.0001 より大きい場合は、通常どおり ceil() を適用します。

編集:これを表示するために Windows を使用している場合に実行できる楽しい例は、組み込みの電卓アプリケーションを開くことです。「4」を入力し、平方根関数を適用します (x^y で y=0.5)。「2」が正しく表示されていることがわかります。ここで 2 を引くと、結果として 0 ではないことがわかります。これは、4 の平方根を計算しようとしたときの内部の丸め誤差が原因です。以前に数値 2 を表示したとき、これらの非常に離れた末尾の数字はおそらく丸め誤差であることがわかっていましたが、残っているのがそれらだけの場合は、ちょっと混乱。

(誰かがこれについて私に話しかける前に、これが単純化しすぎていることは理解していますが、それでも私はこれを適切な例と考えています。)

于 2011-10-19T17:32:48.977 に答える
0

問題は、浮動小数点数が期待どおりになることはめったにないということです。2.7 * 3は、おそらく81.0000000000000000001のようなものになります。ceil()は最大82です。この種の場合、処理するには、ceil / round/floor呼び出しをいくつかの精度チェックでラップする必要があります。それらの余分な微視的な違い。

于 2011-10-19T17:22:02.330 に答える