ascii "15605632.68128593" があり、accurary を失うことなく double に変換したい -
so
double d;
d=(double)atof("15605632.68128593");
printf("%f",d);
printed result is 15605632.681286
何か案は ?
ありがとう - !
ascii "15605632.68128593" があり、accurary を失うことなく double に変換したい -
so
double d;
d=(double)atof("15605632.68128593");
printf("%f",d);
printed result is 15605632.681286
何か案は ?
ありがとう - !
末尾の小数点以下の桁数をすべて取得していない可能性があります。試してみてくださいprintf("%.8f", d)
。
sscanf("15605632.68128593", "%lf", &d)
電話の代わりに試すこともできatof
ます。
atof
toの結果をキャストする必要もありませんdouble
。もうダブルです。しかし、キャストに害はありません。
少なくとも約 6 年前、私がこれを詳細に調べたとき、多くprintf
のscanf
実装は、あなたが想定するほど完全な逆関数として機能しないという意味でバグが多かったことに注意してください。Visual C/C++ と gcc はどちらもネイティブ実装に問題がありました。 この論文は有用な参考文献です。
Cygwin と gcc 4.3.4:
#include <stdio.h>
int main(void)
{
double x;
sscanf("15605632.68128593", "%lf", &x);
printf("%.8f\n", x);
return 0;
}
その後:
# gcc foo.c
# ./a
15605632.68128593
目標:精度を失うことなく "15605632.68128593" を double に変換します。
atof()
プログラムができる最善の方法でそれを達成しました。しかし、15605632.68128593
(16 桁の数字) は ではとして正確に表現できないためdouble
、C
に近似されました1.560563268128593080...e+07
。したがって、わずかな損失ではありますが、精度が失われました。
Typical double
は、約 2 64の異なる数値を表すことができます。参考までに、近くの候補と OP の文字列を以下に示します。
15605632.68128592893... previous double
"15605632.68128593"
15605632.68128593080... closest double
印刷しようとすると、印刷されたものが の正確な値であると考えて、悲しみが生じますx
。代わりに、丸められた値が出力されました。指定子を使用すると、%f
デフォルトで「.」の右側の 6 桁になります。報告され15605632.681286
た 14 桁の数字を指定します。
すべての有効桁数をすべて表示するより良い方法は、 でフォーマットdouble
を使用することです。 '.' の右側の最大桁数であり、10 進指数表記で、a を「往復」するのに必要なすべての桁を示します(文字列の違いなしに、文字列から倍精度文字列へ)。'.' の左側には常に 1 桁が表示されるため、以下の出力では有効数字が表示されます。 私の鉱山と多くの環境では15ですが、さまざまです。%e
DBL_DIG
DBL_DIG
%e
double
%e
1 + DBL_DIG
DBL_DIG
C
すべての有効数字を表示したい場合は、 what is significantを修飾する必要があります。このnextafter()
関数は、次の表現可能な を示しますdouble
。そのため、少なくとも x と次の x を区別するのに十分な桁数を表示したい場合があります。私はお勧めしDBL_DIG + 2
ます。DBL_DIG
十分かもしれませんが 。詳細
プログラムが使用した正確な"1.560563268128593e+07"
値は15605632.68128593079745769500732421875
. これらすべての数字を表示する必要がある状況はほとんどありません。多くの数字を要求しても、ある時点でprintf()
ゼロが返されます。
#include <stdio.h>
#include <float.h>
#include <tgmath.h>
int main(int argc, char *argv[]) {
double x;
x = atof("15605632.68128593");
printf("%.*le\n",DBL_DIG, x); // All digits "round-trip" string-to-double-string w/o loss
printf("%.*le\n",DBL_DIG + 1, x); // All the significant digit "one-way" double-string
printf("%.*le\n",DBL_DIG + 1, nextafter(x, 2*x)); // The next representable double
printf("%.*le\n",DBL_DIG + 3, x); // What happens with a few more
printf("%.*le\n",DBL_DIG + 30, x); // What happens if you are a bit loony
return 0;
}
1.560563268128593e+07
1.5605632681285931e+07
1.5605632681285933e+07
1.560563268128593080e+07
1.560563268128593079745769500732421875000000000e+07