如何计算C++浮点数中的小数位数

How to count amount of decimals in float in C++?

本文关键字:小数 浮点数 C++ 何计算 计算      更新时间:2023-10-16

我需要检查我的任务的浮点数中的小数位数,以验证输入,我该怎么做?

验证

输入应在有输入时完成。您应该检查输入文本并确定它是否可接受。

当十进制数字转换为二进制浮点数

时,该值通常是舍入的,因为二进制浮点不能精确地表示大多数十进制值。因此,当您检查作为此转换结果的float时,您不再具有原始输入,因此无法对原始输入执行精确操作。

您不能希望这样做,因为浮点数保持在二进制浮点数中,而不是十进制。因此,例如,0.1 不能在二进制浮点变量中精确表示。如果你不能准确地表示这个数字,那么你就不能推理它的表示。

如果要将数字表示为十进制,则必须使用十进制表示形式而不是二进制表示形式。

关于这个主题的必读书目:每个计算机科学家都应该知道的浮点运算

这是我

曾经发现的实现,就像user2699298的答案一样,但应该修复一些怪癖。我没有测试所有可能的组合,但对于下面显示的测试,它似乎做得很好。我建议你自己决定这是否足够。

#include <cmath>
template< class T >
unsigned NumberOfDecimalPlaces( const T& num, const unsigned maxNumberOfDecimalPlacesReturned, const T& threshold = 1e-12 )
{
  static_assert( std::is_floating_point< T >::value,
   "NumberOfDecimalPlaces if for floating point numbers only" );
  T number = std::abs( num );
  unsigned numDecimalPlaces = 0;
  while( ( number - std::floor( number ) ) > threshold &&
         ( std::ceil( number ) - number ) > threshold )
  {
    if( ++numDecimalPlaces >= maxNumberOfDecimalPlacesReturned )
      break;
    number *= 10.0;
  }
  return numDecimalPlaces;
}

一些测试:

TEST( NumberOfDecimalPlaces_Is_0_For_0 )
{
  CHECK_EQUAL( 0u, NumberOfDecimalPlaces( 0.0, 20 ) );
}
TEST( NumberOfDecimalPlaces_Yields_Max )
{
  CHECK_EQUAL( 5u, NumberOfDecimalPlaces( 0.11121212, 5 ) );
  CHECK_EQUAL( 5u, NumberOfDecimalPlaces( 0.00000001, 5 ) );
}
TEST( NumberOfDecimalPlaces_WorksOk_ForPrettyNormalNumbers )
{
  CHECK_EQUAL( 1u, NumberOfDecimalPlaces( 0.1, 20 ) );
  CHECK_EQUAL( 1u, NumberOfDecimalPlaces( 0.8, 20 ) );
  CHECK_EQUAL( 8u, NumberOfDecimalPlaces( 0.11121212, 20 ) );
  CHECK_EQUAL( 8u, NumberOfDecimalPlaces( 0.00000001, 20 ) );
  CHECK_EQUAL( 7u, NumberOfDecimalPlaces( 0.0000001, 20 ) );
  //this is represented as 0.0000000109999999
  CHECK_EQUAL( 9u, NumberOfDecimalPlaces( 0.000000011, 20 ) );
}

问题通常是"我需要多少位(精度)?

让我们取两个分数,1/10 和 22/7。

对于 1/10,计算结果为 0.1,是小数点后真的只有一位数字还是 0.1000 仍然有效。 在网络上搜索"有效数字"。

对于分数 22/7,小数点后有多少位数字?
对于无理数,可能存在重复或不重复的序列。 例如,1/3 在第一个小数点后重复。 但是,PI的值不重复吗?

还是您询问小数点前的位数?这可以使用log函数来回答。 number of digits before decimal point = log(number) / log(10);

int decimals_float (float number){
    float num = number;       // local variable to hold the number
    int count = 0;            // variable to count the decimals
    num = abs(num);           // take the absolute value of the number (no negatives)
    num = num - (int)num;     // take off the digit and leave only decimals in the number
    while(num >= 0.1){        // checking until >= 0.1, because if we use != or >= 0 it might not work
        num *= 10;            // multiply the number by 10, to remove one decimal
        count++;              // add one to the decimals
        num -= (int)num;      // take off the digit and leave only decimals in the number
    }
    return count;             // return amount of decimals
}