C++ - How to count the length of the digits after the dot in a double / float?

498 Views Asked by At

How to count the length of the digits after the dot in a double / float?

Without std::string.

So the length after the dot of 1234.5678 is 4.

And how should you correctly use epsilon in such a situation?

I have something like this, one version with epsilon and another without, neither work fully.

// Version 1.
template <typename T> inline constexpr
unsigned int get_length(T x, const bool& include_dot = false) {
    unsigned int len = 0;
    x = abs(x);
    auto c = x - floor(x);
    T factor = 10;
    T eps = epsilon() * c;
    while (c > eps && c < 1 - eps) {
        c = x * factor;
        c = c - floor(c);
        factor *= 10;
        eps = epsilon() * x * factor;
        ++len;
    }
    if (include_dot && len > 0) { ++len; }
    return len;
}

// Version 2.
template <typename T> inline constexpr
unsigned int get_length(const T& x, const bool& include_dot = false, const unsigned int& max_consequtive_zeros = 6) {
    unsigned int len = 0;
    unsigned int zero_count = 0;
    short digit;
    auto decimals = get_decimals(x);
    while (decimals != 0 && len < 14) {
        decimals *= 10;
        digit = decimals;
        if (digit == 0) {
            if (zero_count >= max_consequtive_zeros) { break; }
            ++zero_count;
        }
        else { zero_count = 0; }
        decimals -= digit;
        ++len;
        // std::cout << len << ": " << decimals << " zeros: " << zero_count << "\n";
    }
    if (include_dot && len > 0) { ++len; }
    return len - zero_count;
}
1

There are 1 best solutions below

0
Jeffrey On

A floating point number doesn't store a value in decimal format. It stores it in binary.

For example, if you try to store 234.56 in a float, the closest value that can actually be stored is: 234.55999755859375

1234.5678 is 1234.5677490234375

(go play with https://www.h-schmidt.net/FloatConverter/IEEE754.html to see for yourself)

As such, the length (in decimal digits) of a number in a float is ill-defined. To keep your sanity, please define an epsilon based on the magnitude, not on the number of digits.