1

我需要计算浮点值的小数位数,例如

1234. 567 -> 3
2. 1233 -> 4
4. 2432 -> 4

我最初的想法是:

number = 1234.567;  
...  
while (number - (int)number > 0.0)  
{  
  // Count decimal places  
  ...  
  number *= 10;  
}

但是,这会导致 while 条件下的浮点精度出现问题。唯一安全的解决方法是将浮点数转换为字符串,然后进行基于字符串的小数位数计数。

问题是:我不能使用任何库,无论是第三方库还是 C++ 标准库(由于环境限制)。稍后我知道如何对 char* 进行操作,但是如何在不使用 C++ 库的情况下将我的浮点值转换为字符串(即 char*)?

任何帮助是极大的赞赏。


// 编辑:这是我目前的方法,但仍然不起作用(例如,对于 2.55555)。如何选择合适的阈值?

float abs(float number)  
{  
  return (number > 0.0 ? number : number * -1);  
}  

int round(float number)  
{  
  return (int)(number + 0.5);  
}  

void splitFloat(float* number, int* mantissa, int* exponent)  
{  
  while (abs(*number - round(*number)) > 0.00001)  
  {  
    // *number -= (int)*number; // ???  
    *number *= 10.0;  

    *mantissa = *number;  
    *exponent += 1;  

    cout << "Number: " << *number << ", Mantisse: " << *mantissa << ", Exponent: " << *exponent << endl;  
  }  
}
4

3 回答 3

5

您最初的想法非常接近,问题是浮点会进行舍入,从而使结果不准确。您需要使用阈值而不是与精确的 0.0 进行比较,并且您需要允许(int)操作可能会错误地截断并且您应该改为四舍五入。您可以在截断之前通过添加 0.5 进行舍入。

当位数不再适合时,您也会遇到问题int。您可以通过在每一步减去数字的整数部分来提供帮助。

编辑:要选择适当的阈值,请选择要处理的最大小数位数。如果那是 4,那么您要输出的最小数字是0.0001. 使您的阈值减半,或0.00005。现在,每次将数字乘以 10 时,阈值也乘以 10!

float threshold = 0.00005;
while (abs(*number - round(*number)) > threshold)  
{  
  *number *= 10.0;
  threshold *= 10.0;
  // ...
}

如果您的 float 和 int 都是 32 位,则不必担心减去 int。这样做会使返回尾数变得更加困难。

另外,我之前打算给你一个警告但忘记了:这只适用于正数。

还有一个警告,a 的值范围float非常有限。例如,您可能无法准确表示1234.5670,最后会得到一个无关的数字。更改为double将解决此问题。

于 2012-03-23T17:53:02.997 回答
1

你最初的想法很好,但你需要假设一个最小的错误:

number = 1234.567;
...
while (fabs(number - round(number) > 0.00001)
{
    // Count decimal places
    ...
   number *= 10;
}

请注意,当您说1234.567计算机可能会说1234.5670000001或时1234.566999999,您不想计算所有的 0 或 9。

并当心旋转,而不是截断!

但请注意,对于负数,它可能无法按预期工作。

于 2012-03-23T17:54:57.760 回答
0

我认为您最好计算一下,std::numeric_limits<float>::digits10 - log10(value)因为这是该值将具有的最大十进制数字。如果你有一些东西可以格式化数字,你可以格式化为这个精度并去掉尾随的零。如果没有东西来格式化值,你可能会做很多事情:如果你想要好的结果,这种方法显然很重要。

于 2012-03-23T18:28:28.730 回答