0

これがCコードです。

#include<stdio.h>
#include<math.h>
int main()
{
    double n=10.0;
    double automatic = pow(10.0,log10(n)-log10(5.0));
    printf("%.9lf\n",log10(n)-log10(5.0));
    printf("%.9lf\n",pow(10.0,0.30102996));
    double manual = pow(10.0,0.30102996);
    printf("%.9lf %lf\n",automatic, floor(automatic));
    printf("%.9lf %lf\n",manual,floor(manual));
    return 0;
}

出力は次のとおりです。

0.301029996
1.999999836
2.000000000 1.000000
1.999999836 1.000000

出力から、pow(x、y)ではyが6桁に丸められていると推測できます。これは、署名がpow(double x、double y)であるため、0.301029996が0.301030になるため、automaticの値が2.000000000になる場合は次のようになります。マニュアルと同じ。

私の質問:

  1. 私の推測は正しいですか?
  2. 最初の質問への回答が正しい場合、より正確な結果を達成するために、この四捨五入をどのように回避できますか?
4

1 に答える 1

3

pow6 桁に丸めません。倍精度を使用します。IEEE double の仮数部は 52 ビット (小数点以下約 15 桁) です。その精度で最後の桁まで正確である場合とそうでない場合がありますが、通常は近いです。

0.30102999566398119521373889472410 を底とする 2 の対数の正確な値は(出典: Wolfram Alpha )に近いです。これは無理数であるため、任意の数字システム (10 進数または 2 進数) で正確に表すことはできません。

結果はlog10(n)-log10(5.0)、 が実際よりも 2 の正確な数学的底 10 の対数に近い値を返したことを示しています0.30102996。得られた理由1.999999836は、値を に置き換えたときに手動で値の精度を下げたためです0.30102996。ところで、これは丸められた値ではありません - 9 を数えます。

あなたの呼び出しは( で示されているように)pow(10.0,log10(n)-log10(5.0))よりわずかに少ない結果を返しましたが、9 か所で 2 に丸められるほど十分に近い結果を返しました。double 型を使用しても、これより良くなることはありません。2floor

したがって、「四捨五入を避ける」という意味がよくわかりません。値の精度を下げたくない場合は、手動で 9 桁に丸めないでください。また、コピーするときに桁を逃さないでください ;-)

于 2012-08-12T15:11:06.037 に答える