我试图从double值中获取数字,但它无法正常工作。我试过这个:
int main()
{
double value = 123456.05;
std::cout<<"number of digit::"<<((int)std::log10(value ) + 1);
}
输出:
数字位数:: 6
如何获得确切的位数?预期结果为9。
答案 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