1

私はiPhoneでこのコードを実行しています:

double d = DBL_MAX;
NSString *s = [NSString stringWithFormat:@"%.0f", d];
double dp = atof([s cStringUsingEncoding:[NSString defaultCStringEncoding]]);
NSString *pe = d == dp ? @"YES" : @"NO";

double one = 1;
double dpd = dp / one;
NSString *de = d == dpd ? @"YES" : @"NO";

NSLog(@"### Parsed are equal: %@, divided are equal: %@", pe, de);
NSLog(@"D   : %.0f", d);
NSLog(@"DP  : %.0f", dp);
NSLog(@"DPD : %.0f", dpd);

...そしてこの出力を取得します:

### Parsed are equal: NO, divided are equal: NO
D   : 17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207624549009038932894407586850845513394230458323690322294816580855933212334827479
DP  : 17976931348623155723920577891946972866121062246621938439403251722449088432276750723756897307653964877256701669823356283705419341284625019355047863102662518251134787976961389628366367996124520722972986881016593281354069269901878996004952428787693676134400
DPD : 17976931348623155723920577891946972866121062246621938439403251722449088432276750723756897307653964877256701669823356283705419341284625019355047863102662518251134787976961389628366367996124520722972986881016593281354069269901878996004952428787693676134400

printf()なぜ/のシーケンスatof()が精度を失うのですか(私stringWithFormatprintf内部的にそうすると思います)?これは、DBL_MAXだけでなく、非常に大きな数ごとに発生します(つまり、10000期待どおりに機能しますが、機能DBL_MAX / 2しません)。それを回避する方法はありますか?

4

2 に答える 2

2

すべての 10 進数を 2 進数で表現できるわけではありません。たとえば、0.2(dec) = 0.001100110011...(ビン)。したがって、数値が 10 進文字列から変換されると、切り捨てられる (または丸められる) ことがあります。

2 進数から 10 進数への変換は常に可能ですが、結果が n*log_10(2) よりも長くなることがあります。ここで、n は 2 進数の桁数です。たとえば、0.001(bin) = 0.125(dec) ですが、3*log_10(2)=0.903... したがって、数値が 2 進数からデジタル文字列に変換されると、切り捨てられることもあります。

それが、わずかに異なる結果が得られる理由です。

ここに例があります。仮数が6桁だとします。数値 0.001111(bin) を 10 進数に変換してみましょう。正確な結果は 0.234375 ですが、6 桁の 2 進数を表すには 6*log_10(2)=1.8061 桁しか必要ないため、この数値は 0.23 に丸められます。この場合、1.8061 は 2 に切り上げられます。

0.23 をバイナリに戻すとどうなるか見てみましょう。それは 0.0011101011 です... これは丸められる必要があり、結果は丸めが行われる方法に応じて 0.001110 または 0.001111 になる可能性があります。

于 2012-03-13T07:20:59.223 に答える
1

「有意」、倍精度は53ビットで、10進数で15〜16桁です。17番目の桁で違いがあります(ただし、最初の桁は1です)。

私の推測では (確認していません)、違いは double の下位ビットのみにあるため、出力ルーチンまたは入力ルーチンの丸めの問題です。その場合、目的の C が正しい結果を要求するかどうかはわかりません (正しい結果は、多倍精度演算の使用を義務付けます)。C の実装が異なることは知っています。

于 2012-03-12T17:19:52.880 に答える