1

私はfloat次のように2を掛けようとしています:

float number1 = 321.12;
float number2 = 345.34;
float rexsult = number1 * number2;

見たい結果は110895.582ですが、コードを実行すると110896になります。ほとんどの場合、この問題が発生しています。どの計算機でも、すべての小数で正確な結果が得られます。どうすればその結果を達成できますか?

編集:それはCコードです。XCodeiOSシミュレーターを使用しています。

4

4 に答える 4

3

そのように正確な結果を得ることは決してありません。

まず、number1 ≠ 321.12 です。これは、その値を基数 2 のシステムで正確に表すことができないためです。それには無限のビット数が必要です。

同じことが number2 ≠ 345.34 にも当てはまります。

したがって、最初は不正確な値から始めます。

乗算により有効桁数が2倍になるため、積は丸められますが、float浮動小数点数を掛ける場合は積を再度格納する必要があります。

おそらく、数字には 10 ベースのシステムを使用する必要があります。または、数値の小数部が 2 桁しかない場合は、整数を使用できます (この場合は 32 ビット整数で十分ですが、最終的に 64 ビットが必要になる場合があります)。

32112 * 34534 = 1108955808。

これは、321.12 * 345.34 = 110895.5808 を表します。

于 2012-07-08T09:25:33.150 に答える
1
  • 浮動小数点変数はおおよその表現であり、正確なものではありません。すべての数値が float 変数に「収まる」わけではありません。たとえば、1/10 (0.1) を 2 進変数に入れる方法はありません。ちょうど 1/3 を 10 進数の 1 に入れることができないのと同じです (無限の 0.33333 で近似することしかできません)。
  • このような変数を出力する場合、多くの丸めオプションを適用するのが通常です。それらをすべて設定しない限り、どれが適用されているかを確認することはできません。これは、ストリームに BEFORE << の丸め方を指示できるため、特に << 演算子に当てはまります。

Printf は丸めも行います。http://codepad.org/LLweoeHpを検討してください:

float t = 0.1f;
printf("result: %f\n", t);
--
result: 0.100000

まあ、それはうまく見えます。なんで?printf はデフォルトである程度の精度になり、出力を切り上げたためです。小数点以下 50 桁でダイヤルしてみましょう: http://codepad.org/frUPOvcI

float t = 0.1f;
printf("result: %.50f\n", t);
--
result: 0.10000000149011611938476562500000000000000000000000

それは違いますね。625 の後、float はより多くのデータを保持するための容量を使い果たしました。そのため、ゼロが表示されます。double はより多くの桁数を保持できますが、バイナリの 0.1 は有限ではありません。Double は最終的にあきらめなければなりません: http://codepad.org/RAd7Yu2r

double t = 0.1;
printf("result: %.70f\n", t);
--
result: 0.1000000000000000055511151231257827021181583404541015625000000000000000

あなたの例では、321.12 だけで問題を引き起こすのに十分です: http://codepad.org/cgw3vUKn

float t = 321.12f;
printf("and the result is: %.50f\n", t);
result: 321.11999511718750000000000000000000000000000000000000

これが、人間に提示する前に浮動小数点値を切り上げる必要がある理由です。

電卓プログラムは、float や double をまったく使用しません。10 進数形式を実装します。例えば:

struct decimal
{
     int mantissa; //meaningfull digits
     int exponent; //number of decimal zeroes
};

足し算、引き算、掛け算、割り算など、すべての操作を再発明する必要があります。または、10 進ライブラリを探してください。

于 2012-07-08T09:20:08.257 に答える