C++ 表示任何双精度值所需的最大字符长度是多少?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1701055/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:56:52  来源:igfitidea点击:

What is the maximum length in chars needed to represent any double value?

c++cfloating-point

提问by martin

When I convert an unsigned 8-bit int to string then I know the result will always be at most 3 chars (for 255) and for an signed 8-bit int we need 4 chars for e.g. "-128".

当我将无符号的 8 位 int 转换为字符串时,我知道结果将始终最多为 3 个字符(对于 255),对于有符号的 8 位 int,我们需要 4 个字符,例如“-128”。

Now what I'm actually wondering is the same thing for floating-point values. What is the maximum number of chars required to represent any "double" or "float" value as a string?

现在我真正想知道的是浮点值是一样的。将任何“double”或“float”值表示为字符串所需的最大字符数是多少?

Assume a regular C/C++ double (IEEE 754) and normal decimal expansion (i.e. no %e printf-formatting).

假设一个常规的 C/C++ double (IEEE 754) 和正常的十进制扩展(即没有 %e printf 格式)。

I'm not even sure if the really small number (i.e. 0.234234) will be longer than the really huge numbers (doubles representing integers)?

我什至不确定真正小的数字(即 0.234234)是否会比真正巨大的数字(代表整数的双精度数)长?

采纳答案by Mike Seymour

The standard header <float.h>in C, or <cfloat>in C++, contains several constants to do with the range and other metrics of the floating point types. One of these is DBL_MAX_10_EXP, the largest power-of-10 exponent needed to represent all doublevalues. Since 1eNneeds N+1digits to represent, and there might be a negative sign as well, then the answer is

<float.h>C 或<cfloat>C++ 中的标准头文件包含几个与浮点类型的范围和其他度量有关的常量。其中之一是DBL_MAX_10_EXP表示所有double值所需的最大 10 次幂指数。既然1eN需要N+1数字来表示,而且可能还有负号,那么答案是

int max_digits = DBL_MAX_10_EXP + 2;

This assumes that the exponent is larger than the number of digits needed to represent the largest possible mantissa value; otherwise, there will also be a decimal point followed by more digits.

这假设指数大于表示最大可能尾数值所需的位数;否则,也会有一个小数点后跟更多的数字。

CORRECTION

更正

The longest number is actually the smallest representable negative number: it needs enough digits to cover both the exponent and the mantissa. This value is -pow(2, DBL_MIN_EXP - DBL_MANT_DIG), where DBL_MIN_EXPis negative. It's fairly easy to see (and prove by induction) that -pow(2,-N)needs 3+Ncharacters for a non-scientific decimal representation ("-0.", followed by Ndigits). So the answer is

最长的数实际上是最小的可表示负数:它需要足够的数字来覆盖指数和尾数。该值为-pow(2, DBL_MIN_EXP - DBL_MANT_DIG),其中DBL_MIN_EXP为负数。很容易看到(并通过归纳证明)-pow(2,-N)需要3+N字符进行非科学十进制表示("-0.",后跟N数字)。所以答案是

int max_digits = 3 + DBL_MANT_DIG - DBL_MIN_EXP

For a 64-bit IEEE double, we have

对于 64 位 IEEE double,我们有

DBL_MANT_DIG = 53
DBL_MIN_EXP = -1023
max_digits = 3 + 53 - (-1023) = 1079

回答by Vitaliy Ulantikov

According to IEEE 754-1985, the longest notation for value represented by double type, i.e.:

根据IEEE 754-1985,由 double 类型表示的值的最长表示法,即:

-2.2250738585072020E-308

-2.2250738585072020E-308

has 24 chars.

24 个字符

回答by pmg

You can use snprintf()to check how many chars you need. snprintf()returns the number of chars needed to print whatever is passed to it.

您可以使用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;
}

Note: snprintf()is a C99 function. If a C89 compiler provides it as an extension, it may not do what the above program expects.

注意snprintf()是一个 C99 函数。如果 C89 编译器将其作为扩展提供,则可能无法执行上述程序所期望的操作。

Edit: Changed the link to snprintf()to one that actually describes the functionality imposed by the C99 Standard; the description in the original linkis wrong.
2013: Changed the link backto POSIX site which I prefer over the site of the first edit.

编辑:将链接更改为snprintf()实际描述 C99 标准强加的功能的链接;原始链接中的描述是错误的。
2013 年:将链接改POSIX 站点,我更喜欢第一次编辑站点

回答by pmg

A correct source of information that goes into more detail than the IEEE-754 Specificationare these lecture notes from UC Berkelyon page 4, plus a little bit of DIY calculations. These lecture slidesare also good for engineering students.

IEEE-754 规范更详细的正确信息来源是加州大学伯克利分校第 4 页的这些讲义,以及一些 DIY 计算。这些讲座幻灯片也适合工程专业的学生。

Recommended Buffer Sizes

推荐的缓冲区大小

| Single| Double | Extended | Quad  |
|:-----:|:------:|:--------:|:-----:|
|   16  |  24    |    30    |  45   |

These numbers are based on the following calculations:

这些数字基于以下计算:

Maximum Decimal Count of the Integral Portion

积分部分的最大小数位数

| Single| Double | Extended | Quad  |
|:-----:|:------:|:--------:|:-----:|
|   9   |   17   |    21    |  36   |

* Quantities listed in decimals.

Decimal counts are based on the formula: At most Ceiling(1 + NLog_10(2)) decimals, where N is the number of bits in the integral portion*.

小数计数基于以下公式:最多 Ceiling(1 + NLog_10(2)) 小数,其中 N 是整数部分中的位数*。

Maximum Exponent Lengths

最大指数长度

| Single| Double | Extended | Quad  |
|:-----:|:------:|:--------:|:-----:|
|   5   |   5    |     7    |   7   |
* Standard format is `e-123`.

Fastest Algorithm

最快的算法

The fastest algorithm for printing floating-point numbers is the Grisu2 algorithm detailed in the research paper Printing Floating-point Numbers Quickly and Accurately. The best benchmark I could find can be found here.

打印浮点数的最快算法是研究论文“快速准确地打印浮点数”中详述的 Grisu2 算法。我能找到的最好的基准可以在这里找到。

回答by Charles Salvia

You can control the number of digits in the string representation when you convert the float/double to a string by setting the precision. The maximum number of digits would then be equal to the string representation of std::numeric_limits<double>::max()at the precision you specify.

当您通过设置精度将浮点数/双精度数转换为字符串时,您可以控制字符串表示中的位数。然后,最大位数将等于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;
}

So, the largest number of digits in a doublewith a precision of 10 is 320 digits.

因此,double精度为 10 的a 中的最大位数是 320 位数。

回答by S.Lott

Depends on what you mean by "represent". Decimal fraction don't have exact floating-point representations. When you convert decimal fraction -> binary fraction -> decimal, you do not have exact decimal representations and will have noise bits at the end of the binary representation.

取决于你所说的“代表”是什么意思。小数部分没有精确的浮点表示。当您转换十进制分数 -> 二进制分数 -> 十进制时,您没有精确的十进制表示,并且在二进制表示的末尾会有噪声位。

The question didn't involve starting from decimal, but all source code (and must user input) is decimal, and involves the possible truncation issue. What does "exact" mean under these circumstances?

该问题不涉及从十进制开始,但所有源代码(并且必须由用户输入)都是十进制的,并且涉及可能的截断问题。在这种情况下,“精确”是什么意思?

Basically, it depends on your floating point representation.

基本上,这取决于您的浮点表示。

If you have 48 bits of mantissa, this takes about 16 decimal digits. The exponent might be the remaining 14 bits (about 5 decimal digits).

如果您有 48 位尾数,则大约需要 16 位十进制数字。指数可能是剩余的 14 位(大约 5 个十进制数字)。

The rule of thumb is that the number of bits is about 3x the number of decimal digits.

经验法则是位数大约是十进制位数的 3 倍。

回答by Fred

1024 is not enough, the smallest negative double value has 1077 decimal digits. Here is some Java code.

1024 是不够的,最小的负双精度值有 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);

Here is the output of the program.

这是程序的输出。

1077
-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625

回答by vtomazzi

"What is the maximum length in chars needed to represent any double value?"

“表示任何双精度值所需的最大字符长度是多少?”

The exact answer to this question is: 8 ASCII chars - in a hexadicimal format, excluding the '0x' prefix - 100% accuracy :) (but it's not just a joke)

这个问题的确切答案是:8 个 ASCII 字符 - 十六进制格式,不包括 '0x' 前缀 - 100% 准确度:)(但这不仅仅是一个笑话)

The usable precision of IEEE-754 double is around 16 decimal digits - so excluding educational purposes, representations longer than that are just a waste of resources and computing power:

IEEE-754 double 的可用精度约为 16 位十进制数字 - 因此,不包括教育目的,比这更长的表示只是浪费资源和计算能力:

  • Users are not getting more informed when they see a 700-digit-number on the screeen.

  • Configuration variables stored in that "more accurate" form are useless - every single operation on such number will destroy the accuracy. (excluding changing the sign bit)

  • 当用户在屏幕上看到 700 位数字时,他们并没有获得更多信息。

  • 以“更准确”的形式存储的配置变量是无用的——对此类数字的每一次操作都会破坏准确性。(不包括改变符号位)

If someone needs better realprecision, then there's 80-bit long double with around 18-digit accuracy or f.e. libquadmath.

如果有人需要更好的实际精度,那么有 80 位长的 double,精度约为 18 位或 fe libquadmath。

Regards.

问候。

回答by Greg A. Woods

The maximum number of characters that will be required to print any decimal doublevalue (i.e. in "%f"format) will be for the value of -DBL_MIN(i.e. -0x1p-1022, assuming binary64 IEEE 754 is your double). For that you'll need exactly 325 characters. That's: DBL_DIG + abs(DBL_MIN_10_EXP) + strlen("-0."). This is of course because log10(fabs(DBL_MIN))is 308, which is also abs(DBL_MIN_10_EXP)+1(the +1 is because of the leading digit to the left of the decimal place), and that's the number of leading zeros to the left of the significant digits.

打印任何十进制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);

回答by mwpowellhtx

This is not an ambiguous set of responses at all. I'm looking for something to tell a C#format specifier in order to exercise a parser I am working on. I am randomly generating some test cases, including double or floating point precision constants, and I need the round trip to be preserved. Yes, I know there is "round trip", that is one aspect. But I also need to support Fixedas well as Scientificnotation. So far I like 1079but this does seem excessive to me. Or at the very least my "close enough" comparison needs to take that variance into account pre/post-parse verification.

这根本不是一组模棱两可的回答。我正在寻找一些东西来告诉C#格式说明符,以便练习我正在使用的解析器。我随机生成一些测试用例,包括双精度或浮点精度常量,我需要保留往返。是的,我知道有“往返”,这是一方面。但我还需要支持FixedScientificnotation。到目前为止,我喜欢,1079但这对我来说似乎过分了。或者至少我的“足够接近”比较需要考虑到解析前/解析后验证的差异。