符号なし8ビット整数を文字列に変換すると、結果は常に最大で3文字(255の場合)であり、符号付き8ビット整数の場合は4文字が必要です。 「-128」。
今私が実際に思っているのは、浮動小数点値についても同じことです。 「double」または「float」値を文字列として表すために必要な最大文字数はいくつですか?
通常のC/C++ double(IEEE 754)と通常の10進展開(つまり、%e printfフォーマットなし)を想定します。
本当に小さな数(つまり0.234234)が本当に大きな数(整数を表す倍精度浮動小数点数)よりも長くなるかどうかさえわかりませんか?
標準ヘッダー_<float.h>
_(Cの場合)または_<cfloat>
_(C++の場合)には、浮動小数点型の範囲やその他のメトリックを処理するための定数がいくつか含まれています。これらの1つは_DBL_MAX_10_EXP
_であり、すべてのdouble
値を表すために必要な最大の10のべき乗の指数です。 _1eN
_は_N+1
_の数字を表す必要があり、負の符号もある可能性があるため、答えは
_int max_digits = DBL_MAX_10_EXP + 2;
_
これは、指数が可能な最大の仮数値を表すために必要な桁数より大きいことを前提としています。それ以外の場合は、小数点の後にさらに数字が続きます。
[〜#〜]修正[〜#〜]
最長の数値は、実際には表現可能な最小の負の数値です。指数と仮数の両方をカバーするのに十分な桁数が必要です。この値は-pow(2, DBL_MIN_EXP - DBL_MANT_Dig)
で、_DBL_MIN_EXP
_は負です。 -pow(2,-N)
が非科学的な10進表記(_3+N
_の後にN
桁)を表すには_"-0."
_文字が必要であることを確認(および帰納法で証明)するのはかなり簡単です。だから答えは
_int max_digits = 3 + DBL_MANT_Dig - DBL_MIN_EXP
_
64ビットIEEE doubleの場合、
_DBL_MANT_Dig = 53
DBL_MIN_EXP = -1023
max_digits = 3 + 53 - (-1023) = 1079
_
snprintf()
を使用して、必要な文字数を確認できます。 snprintf()
は、渡されたものを印刷するために必要な文字数を返します。
_/* NOT TESTED */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char dummy[1];
double value = 42.000042; /* or anything else */
int siz;
char *representation;
siz = snprintf(dummy, sizeof dummy, "%f", value);
printf("exact length needed to represent 'value' "
"(without the '\\0' terminator) is %d.\n", siz);
representation = malloc(siz + 1);
if (representation) {
sprintf(representation, "%f", value);
/* use `representation` */
free(representation);
} else {
/* no memory */
}
return 0;
}
_
注:snprintf()
はC99関数です。 C89コンパイラがそれを拡張機能として提供する場合、上記のプログラムが期待することを行わない可能性があります。
Edit:snprintf()
へのリンクを、C99標準によって課された機能を実際に説明するものに変更しました。 元のリンク の説明が間違っています。
2013:リンクbackを 最初の編集のサイト よりも優先するPOSIXサイトに変更しました。
IEEE-754仕様 より詳細な正しい情報源は、4ページの C Berkelyからの講義ノート に加えて、少しのDIY計算です。 これらの講義スライド は工学部の学生にも適しています。
| Single| Double | Extended | Quad |
|:-----:|:------:|:--------:|:-----:|
| 16 | 24 | 30 | 45 |
これらの数値は、次の計算に基づいています。
| Single| Double | Extended | Quad |
|:-----:|:------:|:--------:|:-----:|
| 9 | 17 | 21 | 36 |
* Quantities listed in decimals.
小数は、次の式に基づいています:最大でCeiling(1 + NLog_10(2))の小数。Nは積分のビット数です。部分*。
| Single| Double | Extended | Quad |
|:-----:|:------:|:--------:|:-----:|
| 5 | 5 | 7 | 7 |
* Standard format is `e-123`.
浮動小数点数を印刷するための最速のアルゴリズムは、研究論文で詳細に説明されているGrisu2アルゴリズム 浮動小数点数をすばやく正確に印刷する です。私が見つけた最高のベンチマークは here です。
精度を設定することで、float/doubleを文字列に変換するときに、文字列表現の桁数を制御できます。この場合、最大桁数は、指定した精度でのstd::numeric_limits<double>::max()
の文字列表現と等しくなります。
#include <iostream>
#include <limits>
#include <sstream>
#include <iomanip>
int main()
{
double x = std::numeric_limits<double>::max();
std::stringstream ss;
ss << std::setprecision(10) << std::fixed << x;
std::string double_as_string = ss.str();
std::cout << double_as_string.length() << std::endl;
}
したがって、精度が10のdouble
の最大桁数は320桁です。
1024は十分ではありません。最小の負のdouble値は1077桁です。ここにいくつかのJavaコードがあります。
double x = Double.longBitsToDouble(0x8000000000000001L);
BigDecimal bd = new BigDecimal(x);
String s = bd.toPlainString();
System.out.println(s.length());
System.out.println(s);
これがプログラムの出力です。
1077
-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625
「代表する」が何を意味するかによります。小数部には、正確な浮動小数点表現がありません。小数部->二分数->小数に変換すると、正確な小数表現がなく、バイナリ表現の最後にノイズビットが含まれます。
質問には10進数からの開始は含まれていませんでしたが、すべてのソースコード(およびユーザー入力が必要)は10進数であり、切り捨ての問題が発生する可能性があります。このような状況で「正確」とはどういう意味ですか?
基本的に、それはあなたの浮動小数点表現に依存します。
仮数が48ビットの場合、これは約16桁の10進数になります。指数は残りの14ビット(約5桁の10進数)になる可能性があります。
経験則では、ビット数は小数桁数の約3倍です。
「任意のdouble値を表すために必要な最大文字数は何文字ですか?」
この質問の正確な答えは次のとおりです:8 ASCII chars-16進形式で、「0x」プレフィックスを除きます-100%精度:)(ただし、単なる冗談ではありません)
IEEE-754 doubleの使用可能な精度は約16桁の10進数です。したがって、教育目的を除いて、それよりも長い表現は、リソースと計算能力の無駄遣いです。
ユーザーは、画面に700桁の数字が表示されても、それ以上の情報を得ることはありません。
その「より正確な」形式で格納された構成変数は役に立たない-そのような数でのすべての単一の操作は正確さを破壊します。 (符号ビットの変更を除く)
誰かがより優れたreal精度を必要とする場合、約18桁の精度を備えた80ビットのlong doubleまたはf.e. libquadmath。
よろしく。
10進数のdouble
値(つまり、_"%f"
_形式)を出力するために必要な最大文字数は、_-DBL_MIN
_の値(つまり、-0x1p-1022、binary64を想定) IEEE 754はあなたのdouble
です)。そのためには、正確に325文字が必要です。それは:DBL_Dig + abs(DBL_MIN_10_EXP) + strlen("-0.")
です。もちろん、これはlog10(fabs(DBL_MIN))
が308であり、これがabs(DBL_MIN_10_EXP)+1
でもあるためです(+1は、小数点の左側の先行桁が原因です)。これは、先行の数です。有効数字の左側のゼロ。
_int lz; /* aka abs(DBL_MIN_10_EXP)+1 */
int dplaces;
int sigdig; /* aka DBL_DECIMAL_Dig - 1 */
double dbl = -DBL_MIN;
lz = abs((int) lrint(floor(log10(fabs(dbl)))));
sigdig = lrint(ceil(DBL_MANT_Dig * log10((double) FLT_RADIX)));
dplaces = sigdig + lz - 1;
printf("f = %.*f\n", dplaces, dbl);
_
これは、あいまいな一連の応答ではありません。私が取り組んでいるパーサーを実行するために、C#形式指定子に伝えるための何かを探しています。倍精度または浮動小数点の精度定数を含むいくつかのテストケースをランダムに生成しています。ラウンドトリップを保持する必要があります。はい、「往復」があることは知っています。それが1つの側面です。しかし、固定および科学表記もサポートする必要があります。これまでのところ1079
しかし、これは私には過度に思えます。または、少なくとも「十分に近い」比較では、その差異を考慮して解析前/解析後の検証を行う必要があります。