如何在C ++中获取double值的数字?

时间:2016-06-29 05:05:17

标签: c++ c++11 digit

我试图从double值中获取数字,但它无法正常工作。我试过这个:

int main()
{
    double value = 123456.05;
    std::cout<<"number of digit::"<<((int)std::log10(value ) + 1);
}

输出:

  

数字位数:: 6

如何获得确切的位数?预期结果为9。

2 个答案:

答案 0 :(得分:2)

假设你只需要这个用于双重文字,下面的方法就可以了。

编辑:添加了适用于双打子集的等效函数。它使用穷举搜索所有合理的方式来显示十进制的双倍,如果你需要这个功能真的尖叫,可能有一些方法可以使它更有效。

    #include <iostream>
    #include <string.h>
    #include <assert.h>
    #include <cmath>

    struct double_literal {
            const char* string_value;
            double double_value;
            size_t num_digits;
    };

    #define DOUBLE_LITERAL(x) {#x, x, strlen(#x)};

size_t num_digits(double value){
        //Double gives around 15 accurate digits usually.
        //Disregarding exponential notation, there are hence only 15 reasonable
        //ways to display value, ranging from 15 places in front of the decimal
        //to 15 behind. Figure out which of these is best in terms of error,
        //and then at the end print out how many digits are needed to display
        //the number by removing unecessary zeros.

        //Routine currently only handles values within these bounds
        //If your value is outside, can scale it with a power of ten before
        //using. Special cases for zero and negative values can also be added.

        double window_stop = std::pow(10.0, 15);
        double window_start = 1 + std::pow(10.0, -15);
        assert(value < window_stop);
        assert(value > window_start);

        size_t best_window = 0;
        double best_error = INFINITY;

        double pow_ten_window = 1;
        for(size_t window = 0; window <= 15; window++, pow_ten_window *= 10){
               double rounded = fmod(
                    std::round(value * pow_ten_window),
                    window_stop
               ) / pow_ten_window;
               double error = std::abs(rounded - value);
               if (error < best_error){
                    best_error = error;
                    best_window = window;
               }
        }

        unsigned long long best_rounding = std::llround(
                fmod(
                        value * std::pow(10.0, best_window),
                        window_stop
                )
        );

        size_t best_digits = std::llround(std::log10(best_rounding) + 1);

        //Representation has an integer part => just figure out if we
        //need a decimal point
        if (best_window > 0){
                best_digits++;
        }

        std::cout << best_window << std::endl;

        return best_digits;

}

int main(int argc, char** argv){
        struct double_literal literal DOUBLE_LITERAL(123456.05);
        std::cout << "number of digit::" << literal.num_digits << std::endl;

        //As a function
        std::cout << "numbr of digit::" << num_digits(literal.double_value);
    }

使用文字,您可以稍后在代码中以多种形式获取文字的值。

该函数也适用于非文字,但仅适用于有限的双精度子集。请参阅有关如何概括其余内容的注释。

答案 1 :(得分:0)

您可以将double值转换为string:

double value = 123456.05;
std::string s = std::to_string(value);

之后你需要删除尾随的zeroez(因为现在可能s == "123456.050000"):

s.erase(s.find_last_not_of('0') + 1, std::string::npos);

比获得此字符串的多个字符:

std::cout<<"number of digit::"<< s.length();

(在这种情况下,您将处理&#34;。&#34;作为数字)

因此,以下程序会返回预期结果:

  

数字位数:: 9

但这对于整数值并不完美,因为&#34; 123&#34;将表示为&#34; 123。&#34; (最后还有一个角色)。因此,对于整数值,最好删除尾随&#34;。&#34;在得到长度之前:

void print_nb_digits(double value) {
  std::string s = std::to_string(value);
  s.erase(s.find_last_not_of('0') + 1, std::string::npos);
  if (!s.empty() && !std::isdigit(s.back()))
    s.pop_back();
  std::cout<<"number of digit::"<< s.length();
}

double value = 123456.05;
print_nb_digits(value);

在这种情况下,程序也会返回value = 123456的正确结果:

  

数字位数:: 6