0

我想计算浮点数的小数点后的小数位数。当实数在二进制系统中没有表示时,问题显然会出现,例如3.5689113.

我想知道 - 例如,如果有人在源代码中写这个实数 - 是否有可能得到数字 7,即小数点后的位数

例如,以下天真的代码不起作用:

int main()
{  
    double num = 3.5689113;

    int count = 0;
    num = abs(num);
    num = num - int(num);

    while ( abs(num) >
        0.0000001 )
    {
        num = num * 10;
        count = count + 1;
        num = num - int(num);
    }

    std::cout << count; //48
    std::cin.ignore();
}
4

4 回答 4

3

为了防止浮点近似引入的错误,请尽早将数字转换为整数并使用它。

double num = 3.5689113;

int count = 7;  // a maximum of 7 places
num = abs(num);
int remainder = int(0.5 + 10000000 * (num - int(num)));

while ( remainder % 10 == 0 )
{
    remainder = remainder / 10;
    --count;
}
于 2012-10-26T22:54:06.493 回答
3

When something like that doesn't work, you try to print the numbers.

I did so here, and I found you had some floating number precision issues. I changed the int rounding to ceil rounding and it worked like a charm.

Try putting the ints back and you'll see :)

EDIT: a better strategy than using ceils (which can give the same rounding problems) is to just round the numbers to the nearest integer. You can do that with floor(myNumber+0.5).

Here's the modified code

int main()
{  
    double num = 3.56891132326923333;

    // Limit to 7 digits
    num  = floor(num*10000000 + 0.5)/10000000;

    int count = 0;
    num = abs(num);
    num = num - floor(num+0.5);

    while ( abs(num) >
        0.0000001 )
    {
        cout << num << endl;
        num = num * 10;
        count = count + 1;
        num = num - floor(num+0.5);
    }

    std::cout << count; //48
    std::cin.ignore();

    return 0;
}
于 2012-10-26T22:34:07.130 回答
1

对于浮点类型T,您最多可以std::numeric_limits<T>::digits10精确恢复数字。因此,要确定最后一个非零小数位的位置,您可以使用此值作为精度并格式化数字。为避免使用指数表示法输出,您需要将格式化标志设置为std::ios_base::fixed并考虑非小数位数:

std::ostringstream out;
int non_fraction(std::abs(value) < std::numeric_limits<double>::epsilon()
                 ? 1: (1 + std::log(std::abs(value)) / std::log(10)));
out << std::setprecision(std::numeric_limits<double>::digits10 - non_fraction)
    << std::fixed
    << value;

如果有小数点,您只需要计算直到尾随零序列的位数。

于 2012-10-27T01:48:03.783 回答
0

我建议转换为字符串,然后循环遍历它并计算在您达到句点后出现的字符数。下面是一个示例(可能需要一些小的修补,因为我已经在 C++ 中完成了这个工作);

bool passedRadix = false
int i = 0; // for counting decimals
std::ostringstream strs;
strs << dbl; // dbl is 3.415 or whatever you're counting
std::string str = strs.str();

for(char& c : str) {
   if (passedRadix == true)
       i++; 
   if (c == '.')
       passedRadix = true;

}
于 2012-10-26T22:31:22.397 回答