如何计算C++中浮点小数的多少?

如何计算C++中浮点小数的多少?,c++,floating-point,C++,Floating Point,我需要为我的任务检查浮点数中的小数量,为了验证输入,我如何才能做到这一点?你不能希望这样做,因为浮点数是二进制浮点数而不是十进制数。因此,例如,0.1不能在二进制浮点变量中精确表示。如果你不能准确地表示数字,那么你就不能对它的表示进行推理 int decimals_float (float number){ float num = number; // local variable to hold the number int count = 0;

我需要为我的任务检查浮点数中的小数量,为了验证输入,我如何才能做到这一点?

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

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
}
如果希望将数字表示为十进制,则必须使用十进制表示,而不是二进制表示


此主题的必读读物:

这是我曾经发现的一个实现,与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;
}

问题通常是我需要多少位精度

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

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

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

或者你是在问小数点前的位数? 这可以使用日志函数来回答。
小数点前的位数=lognumber/log10

验证输入应该在您有输入时完成。您应该检查输入的文本并决定它是否可以接受


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

decimals_float0.09==0@DavidHeffernan事实上,我的错。我不应该做>=0.1,我想我应该做>=0.0000001。警告:编译时没有警告,但如果只包含abs声明,则行为完全不正确。哎呀,对我来说事实上,没有什么能解决这个问题。0.0000001有什么特别之处。@user3182683所以,您进行了更改,现在小数为0.099==21。您需要了解可表示性。是否应返回MaxNumberOfDecimalPlacesReturneId是否可以将其重新写入一个简单函数,因为我还不知道模板?只需删除行模板,并用double或float替换所有t。但这正是编译器在幕后所做的,所以现在你知道你可以使用模板版本:P-也就是说,其他答案都非常有效:你确定要像这样计算小数吗?我得到以下错误:“is_floating_point”不是'std'的成员,此行“static_assert std::is_floating_point::value”上的“float”之前应为主表达式,第三个错误“static_assert”未在此范围内声明。我怎样才能修好它们?如果可能的话,不使用C++11.is_浮点/static_断言是C++11。。然而,这只是一个简单的编译时间检查,所以只要删除该行,您就会很好。实际上,如果存储在类型为F的二进制浮点中的值小于std::numeric_limits::digits10位,则可以恢复精确的十进制值,例如,使用Steele&White的Dragon4。你只要数一数数字就行了。诚然,当二进制浮点被规范化时,您会失去尾随零的计数。@DietmarKühl您可以定义往返转换。然而,目前还不清楚这是否是被问到的问题。对我来说,这个问题实际上表明了对浮点表示法的无知,David的回答解决了这个问题。缺少的只是一个关于浮点运算的参考资料。@James它现在就在那里@DietmarKühl:不,您不能仅用浮点值恢复原始值。您还必须具备以下信息:原始值可以表示为十进制数字,但其位数有一定限制。否则,就有无限多个可能的原始值,无法在其中进行选择。由于该问题旨在验证用户输入,因此没有关于数字数量的信息;事实上,这就是我们要寻找的信息。@DietmarKühl如果目标是验证输入中的小数位数,那么人们如何提前知道小数位数小于特定值?浮点变量没有小数位数。它们有二进制的位置。处理小数位数很重要且有界的数字似乎是固定poi的理想情况
nt缩放整数。例如,如果您希望最多小数点后3位,请使用千分之一整数。+1任何错误报告都应包含被拒绝的确切文本,包括在转换过程中不可避免地丢失的前导零和尾随零。
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 ) );
}