我试图得到一个数字在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;
}
答案 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
乘以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
}