简体   繁体   English

max_digits10 的用途是什么?它与 digits10 有何不同?

[英]What is the purpose of max_digits10 and how is it different from digits10?

I am confused about what max_digits10 represents.我对max_digits10代表什么感到困惑。 According to its documentation , it is 0 for all integral types.根据其文档,所有整数类型均为 0。 The formula for floating-point types for max_digits10 looks similar to int 's digits10 's. max_digits10的浮点类型公式看起来类似于intdigits10

To put it simple, 简单来说,

  • digits10 is the number of decimal digits guaranteed to survive text → float → text round-trip. digits10是保证文本存活的小数位数→float→文本往返。
  • max_digits10 is the number of decimal digits needed to guarantee correct float → text → float round-trip. max_digits10是保证正确浮点→文本→浮动往返所需的小数位数。

There will be exceptions to both but these values give the minimum guarantee. 两者都有例外,但这些值给出了最低限度的保证。 Read the original proposal on max_digits10 for a clear example, Prof. W. Kahan's words and further details. 阅读max_digits10上的原始提案max_digits10获得一个明确的例子, max_digits10教授的话和进一步的细节。 Most C++ implementations follow IEEE 754 for their floating-point data types. 大多数C ++实现都遵循IEEE 754的浮点数据类型。 For an IEEE 754 float , digits10 is 6 and max_digits10 is 9 ; 对于IEEE 754 floatdigits106max_digits109 ; for a double it is 15 and 17 . 对于double它是1517 Note that both these numbers should not be confused with the actual decimal precision of floating-point numbers. 请注意,这两个数字不应与浮点数的实际小数精度混淆

Example digits10 例如digits10

char const *s1 = "8.589973e9";
char const *s2 = "0.100000001490116119384765625";
float const f1 = strtof(s1, nullptr);
float const f2 = strtof(s2, nullptr);
std::cout << "'" << s1 << "'" << '\t' << std::scientific << f1 << '\n';
std::cout << "'" << s2 << "'" << '\t' << std::fixed << std::setprecision(27) << f2 << '\n';

Prints 打印

'8.589973e9'      8.589974e+009
'0.100000001490116119384765625'   0.100000001490116119384765625

All digits up to the 6 th significant digit were preserved, while the 7 th digit didn't survive for the first number. 保留了第6 有效数字的所有数字,而第7 数字没有存活第一个数字。 However, all 27 digits of the second survived; 然而,第二个的所有27位数幸存了下来; this is an exception. 是一个例外。 However, most numbers become different beyond 7 digits and all numbers would be the same within 6 digits. 但是,大多数数字在7位数之后变得不同,并且所有数字在6位数内都是相同的。

In summary, digits10 gives the number of significant digits you can count on in a given float as being the same as the original real number in its decimal form from which it was created ie the digits that survived after the conversion into a float . 总之, digits10给出了在给定float可以指望的有效位数,与创建它的十进制形式的原始实数相同,即转换为float后幸存的数字。

Example max_digits10 示例max_digits10

void f_s_f(float &f, int p) {
    std::ostringstream oss;
    oss << std::fixed << std::setprecision(p) << f;
    f = strtof(oss.str().c_str(), nullptr);
}

float f3 = 3.145900f;
float f4 = std::nextafter(f3, 3.2f);
std::cout << std::hexfloat << std::showbase << f3 << '\t' << f4 << '\n';
f_s_f(f3, std::numeric_limits<float>::max_digits10);
f_s_f(f4, std::numeric_limits<float>::max_digits10);
std::cout << f3 << '\t' << f4 << '\n';
f_s_f(f3, 6);
f_s_f(f4, 6);
std::cout << f3 << '\t' << f4 << '\n';

Prints 打印

0x1.92acdap+1   0x1.92acdcp+1
0x1.92acdap+1   0x1.92acdcp+1
0x1.92acdap+1   0x1.92acdap+1

Here two different float s, when printed with max_digits10 digits of precision, they give different strings and these strings when read back would give back the original float s they are from. 这里有两个不同的float ,当用max_digits10个精度数字打印时,它们会给出不同的字符串,这些字符串在读回时会返回它们来自的原始float When printed with lesser precision they give the same output due to rounding and hence when read back lead to the same float , when in reality they are from different values. 当以较低的精度打印时,由于四舍五入而产生相同的输出,因此当读回时导致相同的float ,而实际上它们来自不同的值。

In summary, max_digits10 are at least required to disambiguate two floats in their decimal form, so that when converted back to a binary float, we get the original bits again and not of the one slightly before or after it due to rounding errors. 总之, max_digits10至少需要消除它们十进制形式的两个浮点数,因此当转换回二进制浮点数时,由于舍入错误,我们再次获得原始位而不是稍微之前或之后的位。

In my opinion, it is explained sufficiently at the linked site (and the site for digits10): 在我看来,它在链接的网站(和数字10的网站)充分解释:

digits10 is the (max.) amount of "decimal" digits where numbers digits10是数字的“十进制”数字的(最大)数量
can be represented by a type in any case, independent of their actual value. 在任何情况下都可以用类型表示,与它们的实际值无关。
A usual 4-byte unsigned integer as example: As everybody should know, it has exactly 32bit, 一个通常的4字节无符号整数作为例子:每个人都应该知道,它正好是32位,
that is 32 digits of a binary number. 这是二进制数的32位数。
But in terms of decimal numbers? 但就十进制数而言?
Probably 9. 可能是9。
Because, it can store 100000000 as well as 999999999. 因为,它可以存储1亿和999999999。
But if take numbers with 10 digits: 4000000000 can be stored, but 5000000000 not. 但如果采用10位数字:4000000000可以存储,但5000000000不存储。
So, if we need a guarantee for minimum decimal digit capacity, it is 9. 因此,如果我们需要保证最小十进制数字容量,它是9。
And that is the result of digits10. 这就是数字10的结果。

max_digits10 is only interesting for float/double... and gives the decimal digit count max_digits10仅对float / double ...感兴趣,并给出十进制数字计数
which we need to output/save/process... to take the whole precision 我们需要输出/保存/处理...以获得整体精度
the floating point type can offer. 浮点类型可以提供。
Theoretical example: A variable with content 123.112233445566 理论示例:内容为123.112233445566的变量
If you show 123.11223344 to the user, it is not as precise as it can be. 如果您向用户显示123.11223344,则它不够精确。
If you show 123.1122334455660000000 to the user, it makes no sense because 如果您向用户显示123.1122334455660000000,则没有任何意义,因为
you could omit the trailing zeros (because your variable can´t hold that much anyways) 你可以省略尾随的零(因为你的变量无论如何都不能保持那么多)
Therefore, max_digits10 says how many digits precision you have available in a type. 因此,max_digits10表示您在一个类型中可用的精度位数。

Lets build some context让我们建立一些上下文

After going through lots of answers and reading stuff following is the simplest and layman answer i could reach upto for this.在经历了很多答案并阅读了以下内容之后,这是我可以达到的最简单和外行的答案。

Floating point numbers in computers (Single precision ie float type in C/C++ etc. OR double precision ie double in C/C++ etc.) have to be represented using fixed number of bits.计算机中的浮点数(单精度,即 C/C++ 中的浮点类型等。或双精度,即 C/C++ 中的双精度等)必须使用固定位数表示。

float is a 32-bit IEEE 754 single precision Floating Point Number – 1 bit for the sign, 8 bits for the exponent, and 23* for the value. float 是一个 32 位 IEEE 754 单精度浮点数——1 位用于符号,8 位用于指数,23* 用于值。 float has 7 decimal digits of precision. float 有 7 位小数精度。

And for double type而对于双重类型

The C++ double should have a floating-point precision of up to 15 digits as it contains a precision that is twice the precision of the float data type. C++ double 应具有最多 15 位的浮点精度,因为它包含的精度是 float 数据类型精度的两倍。 When you declare a variable as double, you should initialize it with a decimal value将变量声明为双精度时,应使用十进制值对其进行初始化

What the heck above means to me?以上对我来说到底意味着什么?

Its possible that sometimes the floating point number which you have cannot fit into the number of bits available for that type.有时您拥有的浮点数可能不适合该类型可用的位数。 for eg.例如。 float value of 0.1 cannot FIT into available number of BITS in a computer. 0.1 的浮点值不能适合计算机中可用的 BITS 数量。 You may ask why.你可能会问为什么。 Try converting this value to binary and you will see that the binary representation is never ending and we have only finite number of bits so we need to stop at one point even though the binary conversion logic says keep going on.尝试将此值转换为二进制,您会发现二进制表示永无止境,而且我们只有有限的位数,因此即使二进制转换逻辑说继续进行,我们也需要在某一点停止。

If the given floating point number can be represented by the number of bits available, then we are good.如果给定的浮点数可以用可用位数来表示,那么我们就很好了。 If its not possible to represent the given floating point number in the available number of bits, then the bits are stored a value which is as close as possible to the actual value.如果无法用可用位数表示给定的浮点数,则这些位将存储一个尽可能接近实际值的值。 This is also known as "Rounding the float value" OR "Rounding error".这也称为“舍入浮点值”或“舍入误差”。 Now how this value is calculated depends of specific implementation but its safe to assume that given a specific implementation, the most closest value is chosen.现在如何计算这个值取决于特定的实现,但可以安全地假设给定一个特定的实现,选择最接近的值。

Now lets come to std::numeric_limits<T>::digits10现在让我们来看看std::numeric_limits<T>::digits10

The value of std::numeric_limits::digits10 is the number of base-10 digits that are necessary to uniquely represent all distinct values of the type T, such as necessary for serialization/deserialization to text. std::numeric_limits::digits10 的值是唯一表示类型 T 的所有不同值所必需的 base-10 位数,例如序列化/反序列化为文本所必需的。 This constant is meaningful for all floating-point types.该常量对所有浮点类型都有意义。

What this std::numeric_limits<T>::digits10 is saying is that whenever you fall into a scenario where rounding MUST happen then you can be assured that after given floating point value is rounded to its closest representable value by the computer, then its guarantied that the closest representable value's std::numeric_limits<T>::digits10 number of Decimal digits will be exactly same as your input floating point.这个std::numeric_limits<T>::digits10说的是,每当你陷入必须发生舍入的场景时,你可以放心,在给定的浮点值被计算机舍入到它最接近的可表示值之后,然后它的保证最接近的可表示值的std::numeric_limits<T>::digits10小数位数将与您输入的浮点数完全相同。 For single precision floating point value this number is usually 6 and for double precision float value this number is usually 15.对于单精度浮点值,这个数字通常是 6,对于双精度浮点值,这个数字通常是 15。

Now you may ask why i used the word "guarantied".现在你可能会问为什么我使用“保证”这个词。 Well i used this because its possible that more number of digits may survive while conversion to float BUT if you ask me give me a guarantee that how many will survive in all the cases, then that number is std::numeric_limits<T>::digits10 .好吧,我之所以使用它,是因为在转换为浮点数时可能会有更多的数字存活下来但是如果你问我保证在所有情况下有多少数字会存活下来,那么这个数字就是std::numeric_limits<T>::digits10 . Not convinced yet?还不相信吗?

OK, consider example of unsigned char which has 8 bits of storage.好的,考虑具有 8 位存储空间的 unsigned char 示例。 When you convert a decimal value to unsigned char, then what's the guarantee that how many decimal digits will survive?当您将十进制值转换为 unsigned char 时,那么有多少十进制数字将存活下来的保证是什么? I will say "2".我会说“2”。 Then you will say that even 145 will survive, so it should be 3. BUT i will say NO.然后你会说即使是 145 也会存活,所以它应该是 3。但我会说不。 Because if you take 256, then it won't survive.因为如果你拿 256,那么它就无法生存。 Of course 255 will survive, but since you are asking for guarantee so i can only guarantee that 2 digits will survive because answer 3 is not true if i am trying to use values higher than 255.当然 255 会存活下来,但由于您要求保证,所以我只能保证 2 位数字会存活,因为如果我尝试使用高于 255 的值,答案 3 不正确。

Now use the same analogy for floating number types when someone asks for a guarantee.当有人要求保证时,现在对浮点数类型使用相同的类比。 That guarantee is given by std::numeric_limits<T>::digits10该保证由std::numeric_limits<T>::digits10提供

Now what the heck is std::numeric_limits<T>::max_digits10现在到底是什么std::numeric_limits<T>::max_digits10

Here comes a bit of another level of complexity.这是另一个层次的复杂性。 BUT I will try to explain as simple as I can但我会尽可能简单地解释

As i mentioned previously that due to limited number of bits available to represent a floating type on a computer, its not possible to represent every float value exactly.正如我之前提到的,由于计算机上可用于表示浮点类型的位数有限,因此不可能准确表示每个浮点值。 Few can be represented exactly BUT not all values.很少有人可以准确表示但不是所有值。 Now lets consider a hypothetical situation.现在让我们考虑一个假设的情况。 Someone asks you to write down all the possible float values which the computer can represent (ooohhh...i know what you are thinking).有人要求您写下计算机可以表示的所有可能的浮点值(哦哦......我知道你在想什么)。 Luckily you don't have write all those:) Just imagine that you started and reached the last float value which a computer can represent.幸运的是,您没有写下所有这些:) 想象一下您开始并达到了计算机可以表示的最后一个浮点值。 The max float value which the computer can represent will have certain number of decimal digits.计算机所能表示的最大浮点数都会有一定的小数位数。 These are the number of decimal digits which std::numeric_limits<T>::max_digits10 tells us.这些是std::numeric_limits<T>::max_digits10告诉我们的小数位数。 BUT an actual explanation for std::numeric_limits<T>::max_digits10 is the maximum number of decimal digits you need to represent all possible representable values.但是std::numeric_limits<T>::max_digits10的实际解释是表示所有可能的可表示值所需的最大小数位数。 Thats why i asked you to write all the value initially and you will see that you need maximum std::numeric_limits<T>::max_digits10 of decimal digits to write all representable values of type T.这就是为什么我要求你一开始就写下所有的值,你会发现你需要十进制数字的最大std::numeric_limits<T>::max_digits10来写所有类型 T 的可表示值。

Please note that this max float value is also the float value which can survive the text to float to text conversion but its number of decimal digits are NOT the guaranteed number of digits (remember the unsigned char example i gave where 3 digits of 255 doesn't mean all 3 digits values can be stored in unsigned char?)请注意,这个最大浮点值也是浮点值,它可以在文本到浮点到文本的转换中幸存下来,但它的小数位数不是保证的位数(记住我给出的 unsigned char 示例,其中 3 位 255 没有'不是说所有 3 位数的值都可以存储在 unsigned char 中吗?)

Hope this attempt of mine gives people some understanding.希望我的这次尝试能给大家一些理解。 I know i may have over simplified things BUT I have spent sleepless night thinking and reading stuff and this is the explanation which was able to give me some peace of mind.我知道我可能把事情简单化了,但我花了一个不眠之夜思考和阅读东西,这是能够让我安心的解释。

Cheers !!!干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM