PHPで任意精度の算術関数を使用する必要があるのはいつですか?


9

私の同僚は、帯域幅の計算にBinary Calculator関数を使用しています。テラバイトと同じくらい、割り振り時にパーセンテージが分割されます。バイトを失うことがないように、彼のこれらの関数の使い方は正しいようです。彼は今、すべてにそれらを使用しているようですが。

マニュアルは言うだけです:

任意精度の数学のために、PHPは文字列として表される任意のサイズと精度の数値をサポートするBinary Calculatorを提供します。

どのくらいのサイズですか?本当に必要ですか?PHPのデフォルトのフロートはどのくらいの大きさですか?これまたは覚えておくべきことに関して何か良いアドバイスはありますか?

回答:


14

PHPの整数のサイズはプラットフォームに依存します。

整数のサイズはプラットフォームに依存しますが、最大値は約20億が通常の値です(32ビットの符号付き)。通常、64ビットプラットフォームの最大値は約9E18です。PHPは符号なし整数をサポートしていません。PHP 4.4.0およびPHP 5.0.5以降、整数のサイズは定数PHP_INT_SIZEを使用して、最大値は定数PHP_INT_MAXを使用して決定できます。

フロートのサイズはプラットフォームに依存します:

浮動小数点数のサイズはプラットフォームに依存しますが、精度が約14桁の10進数で最大1.8e308が一般的な値です(64ビットIEEE形式)。

そして、フロート精度に関するマニュアルに大きな赤い警告があります:

浮動小数点数の精度は制限されています。システムに依存しますが、PHPは通常、IEEE 754倍精度フォーマットを使用します。これにより、1.11e-16の順序で丸められるため、最大の相対エラーが発生します。非初等算術演算では、より大きなエラーが発生する可能性があります。もちろん、いくつかの演算を組み合わせる場合は、エラーの伝播を考慮する必要があります。

さらに、0.1や0.7のように、基数10で浮動小数点数として正確に表現できる有理数は、仮数のサイズに関係なく、内部で使用される基数2で浮動小数点数として正確に表現されません。したがって、精度を少し失うことなく、内部のバイナリに変換することはできません。これは混乱を招く結果につながる可能性があります。たとえば、floor((0.1 + 0.7)* 10)は、内部の表現が7.9999999999999991118 ....のようになるため、通常は期待される8ではなく7を返します。

BC Math拡張機能は依存関係をバイパスするため、大きな整数を文字列として明示的に指定でき、PHPによる整数リテラルの解釈を回避できます。GMP機能はまた、同様の方法では良い選択肢と仕事です。any size文字列の最大サイズを参照していることを安全に想定できます。これは、使用可能なメモリによってのみ制限されます

紐が非常に大きくなっても問題ありません。PHPでは、文字列のサイズに制限はありません。唯一の制限は、PHPが実行されているコンピュータの使用可能なメモリです。

それが理にかなっているかどうかは、ケースごとにのみ決定できます。拡張機能の実際のパフォーマンスの問題に気づいたことはありませんが、ネイティブの代替機能ほど高速ではありません。


本当に必要ですか?

必要な場合にのみ必要ですが、それが常に明白であるとは限りません。露骨な虐待を簡単に特定することはできますが、より複雑なシナリオについて簡単に議論することはできません。

同僚と話し合って、彼がどこでもそれらを使用する理由を見つけてください。オーバーフローは非常に醜い状況につながり、特定および解決するのが非常に難しいと私は思います。彼がBC Mathを悪用している場合、それは彼がひどくひどく行き詰まり、できるだけ安全にプレイしようとしたためである可能性があります。BC Mathを使用することには本質的に問題はありませんが、それ以外では取るに足らないパフォーマンスペナルティは、いくつかのシナリオで深刻な問題になる可能性があります。パフォーマンスの問題に気づいた場合は、アプリケーションのプロファイルを作成し、それがBC Mathに関連していることを確認してください。

常に計算が正しく機能することを忘れないでください。

  • 対象とするすべてのシステムに、個々の開発者用マシンと(もちろん)プロダクションマシンが含まれています。
  • 可能なシステム/プラットフォームのアップグレードまたはダウングレードに関係なく。

マルチプラットフォーム開発では、最低限度を常にハード限度と見なす必要があります。計算が制限(結果を含む)を超えないことが確実である場合は、BC Mathを使用しても意味がありません。

しかし、あなたが説明しているのが彼がecho bcadd("1", "2");よりecho 1+2;も好むということなら、まあ、幸運を祈ります!


PerconaのMySQL Performanceブログで、ブックマークの膨大なリストである非常に興味深く関連性の高いブログ投稿、PHPでのIntegers、はさみでの実行、および移植性を見つけました。それは古い(2007)ですが、PHPでの整数移植性を備えたさまざまなsnafusの概要を示しています。


1
文字列を使用することは、任意の精度の計算にはまったく必要ありません(実際、内部的に処理するのはかなり醜くて複雑だと思います)。これは、文字列を取得する簡単な方法にすぎません。

@delnan文字列は、バイナリ計算機関数にパラメーターを渡すために使用されます。明らかに、整数を使用できる場合、関数は必要ありません...これby representing arbitrary precision numbers as stringsはマニュアルから取得したものであり、内部で何が起こっているかの提案としてそれを読みましたか?-つまり、ネイティブスピーカーではなく、その部分をどのように改善できますか?
yannis

はい、私は「BC Mathは文字列を内部的に使用する」(実際にはそうではないことを疑うために任意精度の算術を十分に理解していますが)と読むことができると思います。 。私もネイティブスピーカーではありませんが、文字列を通じてBC Mathと対話する方が安全だと思います。

@delnanありがとう、私はあなたの意味を理解しています。私の考えでは、このフレージングは​​内部で何が起こっているかを示唆するものではありません。ライブラリの使用は実際には内部で何が起こっているかを気にしないためですが、混乱を招き、誤解を招く可能性があります。
yannis

@delnan回答を更新しました。
yannis

4

これまたは覚えておくべきことに関して何か良いアドバイスはありますか?

PHPでのBC数学関数の使用には、長所と短所があります。

利点:

  • 「任意のサイズと精度の数値」で数値の基本的な計算を実行できます。

短所:

  • 計算はネイティブではありません(IntegerまたはFloatでの計算はPHPネイティブであり、多くの場合CPUネイティブです)
  • 文字列として管理される数
  • コードが読みにくい

したがって、BC Mathは特定の使用法のために予約されており、式やアルゴリズムさえも難読化し、大規模な計算を遅くする可能性があることがわかります。

そのため、ビジネス計算を理解して、そのような関数が本当に必要な場合とそれらが役に立たない場合を把握することをお勧めします。したがって、ここではコードの速度と可読性に焦点を当てる必要があります。次に、BC Mathの使用に関するプロジェクトのコーディング規約を選択することが適切です。

そのためには、PHPネイティブ計算とBC数学関数の技術的な違いを理解する必要があります。それはあなたの質問です「どのくらいのサイズですか?PHPのデフォルトのフロートはどのくらいの大きさですか?」

どのくらいのサイズですか?

私たちは彼に関する多くの文書を見つけることができません。おそらく、PHPで文字列を使用できる限りです。

PHPのデフォルトのフロートはどのくらいの大きさですか?

「フロートのサイズはプラットフォームに依存しますが、およそ14桁の10進数の精度で最大1.8e308が一般的な値です(64ビットIEEE形式)。」

詳細はPHPマニュアルをご覧ください。

PHP は大きな整数で計算を実行するGMP関数も提供することに注意してください。


1

GMPよりもbcmathの方が使いやすいと思います。これまでのところ、PHPでGMPを使用して浮動小数点計算を処理する方法を見つけることはできませんでした。PHPリリースでは、浮動小数点の要素はすべて省略されているようです。だから私は(今のところ)bcmathを使います。

PHPのGMPは、数論計算に向けられているようであり、pi(またはe)の小数などの数値計算には似ていません。


0

「これや覚えておくべきことについて何か良いアドバイスはありますか?」

次のものに代わるものはありません。

  1. PHPプラットフォームの制限を理解している。

  2. 問題の計算要件を理解する。

さらに、計算の数学をある程度理解しておくと、常に役に立ちます。


0
"When must arbitrary precision arithmetic functions be used in PHP?"

私のサイトでは、PHPでbcmath関数を使用しなければならないことを聞いたことがありません。インターネット上の最大規模のサイトのほとんどはかなりの量のPHPを使用し、2億4,000万を超える"サイトはPHPを使用してコーディングされています。

bcmathは通常、intではなく「long」が必要な状況ではなく、またはintまたはfloatの特定のサイズが問題になる場合ではなく、数値が非常に大きくまたは非常に小さくなる極端な場合に使用されます。

"How much is any size?"

bcmathはメモリによってのみ制限され、実際にはこれは実際の制限ではありません。bcmathを使用した簡単なテストでは、2 ^ 1000000(301,030+桁、100万は7桁のみ)より大きい数値と「0.1-2 ^ 1000000」を処理できることを示しています。

パフォーマンスに関する限り、bcmathは高速ですが、大量のメモリを消費する可能性があります。これは基本的に、ペンインパッドを使用して(人間として)行うのと同じ方法で数値を計算します。現実的な数値は数百ステップで処理でき、通常は数ミリ秒の時間しかかかりません。しかし、これらの「数百」の文字列コピーはメモリに追加されます。上記の数値(2 ^ 1000000)は計り知れないほど大きく、かなり古いノートパソコンの処理には2〜3秒かかります。

"Is it really necessary?"

要するに、はい、しかし非常にまれです。

たとえば、SHA-1ハッシュは実際には数値であり、文字列ではありません。SHA-1を使用した最大可能数は2 ^ 160、つまり1,461,501,637,330,902,918,203,684,832,716,283,019,655,932,542,976です。ネイティブデータタイプを使用してこのような数値を処理する方法はありません。分散アルゴリズムでは、SHA-1ハッシュ(数値として)の処理はかなり一般的です。

繰り返しになりますが、これはまれですが、必要な場合、システムや好みのフレームワークに関係なく、実際に代用するものはありません。

"Advise"

bcmathは、必要なものであることがわかっている場合、または単に数値で遊んで楽しむ場合を除いて、使用しないでください。それは何も壊さず、顕著なパフォーマンスの問題を引き起こすべきではありませんが、ほとんどの問題はPHPの標準データ型を使用して解決できます。


SHA-1は、内部でいくつかの32ビット整数で動作します。外部的には、バイトシーケンスで動作します。つまり、大きな数字よりも文字列に近いのです。160ビット整数として扱うことはめったに役に立ちません。(内部的に大きな整数を使用するRSAなどの暗号化の他の領域がありますが、サイドチャネル攻撃を
引き起こす

うーん、MITがChordを作成したときに間違っていたと思います。私はI型として崩壊しつつあるクラウドを聞くことができます:P
JSON

ところで、SHA1の内部に関してはあなたの権利です。
JSON 2014年

ChordはSHA-1ハッシュを大きな数として解釈する場合があります。SHA-1が大きな整数に関連しているからではなく、SHA-1の上に構築されたプロトコルがそうするのが便利であるとわかるかもしれないからです。DHTはハッシュ間の距離メトリックを使用します。ハッシュは大きな整数を使用して表現される場合があります。
CodesInChaos 2014年

まず、大きな整数は疑似型です。それらは本来どのシステムにも存在しません。それらは内部では文字列ですが、一部の実装では、コード内で大きな整数を実際の「数値」として表現できます(Javaなどの「1234323456654322345」ではなく1234323456654322345)。このような実装では、数値コードがコンパイルされるときにchar文字列が作成されます。
JSON
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.