获取c中的数字小数位数?

时间:2015-02-05 08:58:05

标签: c

我试图得到一个数字在c中的小数位数:0.0001 - > 4位小数,3,54235 - > 5位小数,依此类推(如果你没有得到它,逗号后面的数字数。)我们的老师sais可以通过两种方式完成,使用字符串而不使用字符串。我想我会继续不使用字符串,因为我没有使用字符串的经验。

所以这就是我想出来的

int funzione1(float decimals){
  int x=1,c=0,y=1;
  while (x!=0){
      if((decimals - y) > 0){
          y = y / 10;
          c++;
      }else{
          decimals = decimals - y;
      }
      if(decimals == 0)
          x=0;
  }
  return c-1;
}

当调用函数时,它应该返回我想到的小数位数,但它没有,实际上它会陷入无限循环。

这段代码背后的理念是为数字“字符串”中的每个数字设置为0,然后检查总数是否为0

3.456 c = 0

0.456 c = 1

0.056 c = 2

0.006 c = 3

0.000返回c

但是这给我留下了两个问题1如何在逗号之前去除数字量,如5564.34234这样的代码将不起作用,因为在全数为0之前它将计为8,因此不返回右边小数位数。我设计的代码不起作用。只是陷入无限循环。我不知道循环的无限性在哪里创建。

如何让这段代码生效?

PS。我在Java中发现了这篇关于这个问题的文章:How to find out how many decimals a number has?但它使用了字符串,我不喜欢这样,因为我不知道如何使用字符串。

编辑:这是我试过的另一段代码,当你输入一个大于1的数字时,它会输出50,如果数字低于0,则输出为0(我不明白,不是这里有代码:

int funzione1(float decimals){
    int i=0;
    while(decimals!=((int)decimals)){
        i++;
        decimals=decimals*10;
    }
    return i;
}

4 个答案:

答案 0 :(得分:2)

你最好的选择是将输入作为字符串读取,然后只计算'。'之后的数字。浮点数不是精确表示,即十进制值在内部以二进制形式存储,并且可能不完全代表真实的十进制值。但是,每个二进制表示都是一些带有限数字的十进制数。

在SO中查看this答案。

答案 1 :(得分:2)

如果您不关心舍入,那么您不需要计算小数位数,您只需计算二进制位数即可。这是因为10仅包含2作为因子,因此10 ^ n和2 ^ n具有相同数量的2s作为因子。计算二进制位数的最快方法是获得浮点数的指数。

e.g。二进制0.001取3个小数位代表0.125,0.0001取4 0.0625。

您可以获取值的小数部分并继续乘以2并删除整数,因为人们建议使用10(它将给出相同的答案)。

或者您可以在优化解决方案方面获得更多乐趣(places函数可以完成大部分工作):

#include <math.h>

int saturateLeft (unsigned int n) {
  n |= (n <<  1);
  n |= (n <<  2);
  n |= (n <<  4);
  n |= (n <<  8);
  n |= (n << 16);
  return n;
}

int NumberOfSetBits(int i)
{
  i = i - ((i >> 1) & 0x55555555);
  i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
  return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}

int places (double num) {
  int exponent;
  float mantissa = frexp (num, &exponent);

  /* The answer we are looking for is given by the 
     (number of bits used by mantissa) - the exponent.
  */

  unsigned intMantissa = scalbnf (mantissa, 32);
  /* Could also be got by doing:
     intMantissa = *(unsigned *)&mantissa << 9;
  */

  /* To work out how many bits the mantissa covered we 
     need no gaps in the mantissa, this removes any gaps.
  */

  intMantissa = saturateLeft (intMantissa);
  int bitCount = NumberOfSetBits (intMantissa);

  /* bitCount could also be found like this:
     intMantissa = ~intMantissa;
     int bitCount = 32 - ilogb (intMantissa) - 1;
  */

  int result = bitCount - exponent;
  if (result < 0)
    return 0;

  return result;
}

找到了bitCounting算法here

答案 2 :(得分:1)

这是一个想法:

  • 以浮点数开头,比如a​​ = 3.0141589
  • 通过减去积分部分,使小数点0之前的部分为零,留下0.0141589
  • 在循环中,将a乘以10并保存整数部分,这将为您提供0到9之间的数字列表。
  • 从此列表中,导出小数位数

此算法中有一些有趣的细节供您查找,我不会破坏等待您的乐趣或惊喜。

答案 3 :(得分:0)

考虑我的基于字符串的解决方案:

#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <math.h>
#include <float.h>
int countDecimals(double x)
{
    int cnt;
    char * ptr;
    char str[20] = {0};
    // take  fractional part from x
    double ip;
    double fp = modf (x , &ip);
    // printf("%lg + %.15lg\n", ip, fp); // uncomment for debugging
    // to be sure that Decimal-point character is '.'
    setlocale(LC_NUMERIC, "C");
    // make string from number's fractional part asking maximum digits (DBL_DIG)
    sprintf(str,"%.*lg", DBL_DIG, fp);
    // find point
    if( ptr = strchr(str, '.') )
    {
        // calculate length of string after point
        // length - (point position from beginning) - point = number of decimals
        cnt = strlen(str) - (ptr - str) - 1;
    }
    else
    {
        cnt = 0;
    }
    return cnt;
}

int main (void)
{
    double fn;
    printf("Enter a float number: ");
    scanf("%lf", &fn);
    printf("Your number has %d decimals.\n" , countDecimals(fn) );
    return 0;
}

但是你应该记住可能的舍入和准确性错误。

注意:我使用了double类型,因为应使用float函数modff代替modf,而FLT_DIG代替DBL_DIG }