How are FLT_DIG, DBL_DIG, and LDBL_DIG determined in C [duplicate]
Asked Answered
S

2

9

FLT_DIG, DBL_DIG, LDBL_DIG are the number of decimal digits that can be accurately represented by float, double, and long double types respectively.

#include <stdio.h>
#include <float.h>

int main(void)
{
  printf("%d, %d, %d\n", FLT_DIG, DBL_DIG, LDBL_DIG);
  return 0;
}

prints 6, 15, and 18. The standard, at section 5.2.4.2.2, gives the accurate formula -- e.g. for float, p = 24, and b = 2:

enter image description here

But I'm not clear how the above formula (the "otherwise") is derived. Can someone please explain?

The below is the reasoning I followed which does not answer the question. Consider type float which has 23 bits in the significand (IEEE-754 standard). The maximum binary integer that can be accurately represented is:

  100...00 (25 digits total, because we have an implicit 1)
  = 2^24
  = 10^(24*log(2)) 

Hence # decimal digits:

= floor(24*log(2)) = 7

And not floor(23 * log(2)) = 6 as the standard states.

Shakeup answered 30/11, 2019 at 21:57 Comment(2)
To save people some searching, can you say where this formula can be found in the standard? In particular, how are p and b defined?Biracial
Why floating-points number's significant numbers is 7 or 6 is a potential dupe.Figurate
F
5

How are FLT_DIG, DBL_DIG, and LDBL_DIG determined (?)

Roughly, with p binary digits, p*(log102) decimal digits can be encoded. Every binary digit contributes to about .3 decimal digits.

Recall floating point values and numbers as decimal text with n signification digits and an exponent are distributed linearly within a larger logarithmic distribution.

The -1 of below comes from worst case alignments issues where the distribution of decimal values is densest relative to the binary values. There is no -1 if the float base was 10, as the distribution aligns.

enter image description here

The below is the reasoning I followed which does not answer the question. ...

OP's line of reasoning fails per #6 in here. The alignment of decimal values to binary ones does not always "work".

A float as binary32 example.

  1. In the range [233 or 8,589,934,592 ... 234 or 17,179,869,184), again, 223 (8,388,608) values are linearly encoded: 1024.0 apart from each other. In the sub range [9,000,000,000 and 10,000,000,000), there are about 976,562 different values.

  2. As text, the range [9,000,000*103 and 10,000,000*103), using 1 lead digit and 6 trailings ones, there are 1,000,000 different values. Per #1, In the same range, there are less than 1,000,000 different float values. Thus some decimal textual values will convert to the same float. In this range we can use 6, not 7, digits for distinctive conversions.

Figurate answered 30/11, 2019 at 23:31 Comment(0)
A
2

Here's how I think about it. Disclaimer: I'm just a programmer, not a mathematician, let alone a number theorist, for whom the question you're asking forms (I believe) a central theorem.

Everybody knows base 10: Two digits gives you 102 or 100 values, three digits gives you 103 or 1000 values, etc.

Every programmer knows base 2: Eight bits gives you 28 or 256 values, sixteen bits (two bytes) gives you 216 or 65536 values, etc.

So the question is, how many bits are there in a decimal digit?

Well, 23 is 8, so it's more than 3 bits. And 24 is 16, so it's less than 4 bits.

You know about logarithms, right? (The formula you asked about has one in it, so I'm hoping you know at least a little bit about them.) Logarithms are the inverse of exponentiation. If 102 is 100, then log10 100 is 2. If 28 is 256, then log2 256 is 8.

So the number of binary bits in a decimal digit is log2 10, which it turns out is about 3.322. (See, I was right: greater than 3, less than 4.)

We can go the other way, too. If 216 is 65536, how many decimal digits do 16 bits correspond to? Clearly it's around 5: we needed 5 digits to write 65536. But actually it must be a little less than 5, because with 5 decimal digits we could represent up to about 99999 different values, and that's more than 16 bits.

And in fact, by our earlier result that there are 3.322 binary bits in a decimal digit, we'd need something like 16 ÷ 3.322 ≊ 4.8 decimal digits to exactly represent 16 bits.

Finally, let's look at floating point. According to Wikipedia, IEEE 754 single-precision floating-point format (which is typically a C float) has 24 bits' worth of significant (aka "mantissa"). Using our handy-dandy conversion factor, that's equivalent to something like 24 ÷ 3.322 ≊ 7.2 decimal digits. (Actually it's somewhat more complicated than that, due to complicating factors in IEEE-754 such as denormalized numbers and the implicit 1 bit, but 7.2 digits will do as an answer for now.)

I've led you mildly astray, because I've been using a conversion factor of log210 ≊ 3.322 to go back and forth between binary bits and decimal digits, while the formula you cited has log10 b (where for us b is probably 2). Also, look: they're multiplying by log10 b, while I've been dividing by log210. Surprise, surprise: log210 == 1 / (log10 2). (I'm sure there's an elegant proof of that, but this answer is getting too long.)

Alberik answered 30/11, 2019 at 22:43 Comment(7)
Thanks! But that is what I came up with too :-) But my question is why it is 6? I really need precise answer.Shakeup
@user3124390 Oh! Sorry for lecturing you on what you already knew, then. Unfortunately this is about as far as I go. It's pretty obvious where the floor function comes from (there's no such thing as 7.2 digits, so you can really only guarantee 7), but I don't know how to explain the discrepancy between 6 and 7.Alberik
If @EricPostpischil happens by and has time, I bet he can explain it better.Alberik
For the thing about logs to different bases, simply note that log_a(b) = log_c(b) / log_c(a) for any c, so that when a,b are interchanged you get a reciprocal.Biracial
"because with 5 decimal digits we could represent 10000 different values" I think you mean 100000?Biracial
@NateEldredge I did, although 100000 looks wrong, because it's 6 digits. But fixed. Thanks.Alberik
@Shakeup See Eric Postpischil's answer at How to calculate float type precision and does it make sense?Alberik

© 2022 - 2024 — McMap. All rights reserved.