c语言小数点右移
Moving decimal place to right in c
我是 C 的新手,当我 运行 下面的代码时,输出的值是 12098 而不是 12099。
我知道使用小数总是会有一定程度的不准确,但是有没有办法每次都将小数点准确地移动到正确的两位?
#include <stdio.h>
int main(void)
{
int i;
float f = 120.99;
i = f * 100;
printf("%d", i);
}
您可以使用
float f = 120.99f
或
double f = 120.99
默认情况下,c 将浮点值存储为 double,因此如果将它们存储在 float 变量中,则会发生隐式转换,这很糟糕...
我认为这可行。
使用round
函数
float f = 120.99;
int i = round( f * 100.0 );
但是请注意,float
通常只有 6 或 7 位精度,因此有一个最大值可以使用。无法正确转换的最小 float
值是数字 131072.01
。如果乘以 100 并四舍五入,结果将为 13107202
.
您可以使用 double
值来扩展数字的范围,但即使 double
的范围也是有限的。 (A double
有 16 或 17 位精度。)例如,下面的代码将打印 10000000000000098
double d = 100000000000000.99;
uint64_t j = round( d * 100.0 );
printf( "%llu\n", j );
这只是一个例子,找到超过 double
精度的最小数字留作 reader.
的练习
对整数使用定点运算:
#include <stdio.h>
#define abs(x) ((x)<0 ? -(x) : (x))
int main(void)
{
int d = 12099;
int i = d * 100;
printf("%d.%02d\n", d/100, abs(d)%100);
printf("%d.%02d\n", i/100, abs(i)%100);
}
如果您想继续将数字作为浮点数进行运算,那么答案或多或少是否。对于 小 数字,您可以执行各种操作,但随着数字变大,您会遇到问题。
如果您只想打印数字,那么我的建议是将数字转换为字符串,然后将小数点移到那里。这可能会稍微复杂一些,具体取决于您在字符串中表示数字的方式(指数等)。
如果您希望它起作用并且您不介意不使用浮点数,那么我建议您研究任意数量的固定十进制库。
您的问题是浮点数在内部使用 IEEE-754 表示。那是在基数 2 中而不是在基数 10 中。0.25
将有一个精确的表示,但 0.1
没有,120.99
也没有。
真正发生的是,由于浮点数不准确,最接近十进制值120.99
乘以100
的ieee-754浮点数略低于12099
,所以它是截断 到 12098
。你的编译器应该警告你你有一个从 float 到 in 的 截断(我的有)。
获得预期结果的唯一万无一失的方法是在截断为 int 之前将 0.5
添加到 float 中:
i = (f * 100) + 0.5
但是注意浮点在处理十进制值时本质上是不准确的。
编辑:
当然对于负数,应该是i = (f * 100) - 0.5
...
我是 C 的新手,当我 运行 下面的代码时,输出的值是 12098 而不是 12099。
我知道使用小数总是会有一定程度的不准确,但是有没有办法每次都将小数点准确地移动到正确的两位?
#include <stdio.h>
int main(void)
{
int i;
float f = 120.99;
i = f * 100;
printf("%d", i);
}
您可以使用
float f = 120.99f
或
double f = 120.99
默认情况下,c 将浮点值存储为 double,因此如果将它们存储在 float 变量中,则会发生隐式转换,这很糟糕...
我认为这可行。
使用round
函数
float f = 120.99;
int i = round( f * 100.0 );
但是请注意,float
通常只有 6 或 7 位精度,因此有一个最大值可以使用。无法正确转换的最小 float
值是数字 131072.01
。如果乘以 100 并四舍五入,结果将为 13107202
.
您可以使用 double
值来扩展数字的范围,但即使 double
的范围也是有限的。 (A double
有 16 或 17 位精度。)例如,下面的代码将打印 10000000000000098
double d = 100000000000000.99;
uint64_t j = round( d * 100.0 );
printf( "%llu\n", j );
这只是一个例子,找到超过 double
精度的最小数字留作 reader.
对整数使用定点运算:
#include <stdio.h>
#define abs(x) ((x)<0 ? -(x) : (x))
int main(void)
{
int d = 12099;
int i = d * 100;
printf("%d.%02d\n", d/100, abs(d)%100);
printf("%d.%02d\n", i/100, abs(i)%100);
}
如果您想继续将数字作为浮点数进行运算,那么答案或多或少是否。对于 小 数字,您可以执行各种操作,但随着数字变大,您会遇到问题。
如果您只想打印数字,那么我的建议是将数字转换为字符串,然后将小数点移到那里。这可能会稍微复杂一些,具体取决于您在字符串中表示数字的方式(指数等)。
如果您希望它起作用并且您不介意不使用浮点数,那么我建议您研究任意数量的固定十进制库。
您的问题是浮点数在内部使用 IEEE-754 表示。那是在基数 2 中而不是在基数 10 中。0.25
将有一个精确的表示,但 0.1
没有,120.99
也没有。
真正发生的是,由于浮点数不准确,最接近十进制值120.99
乘以100
的ieee-754浮点数略低于12099
,所以它是截断 到 12098
。你的编译器应该警告你你有一个从 float 到 in 的 截断(我的有)。
获得预期结果的唯一万无一失的方法是在截断为 int 之前将 0.5
添加到 float 中:
i = (f * 100) + 0.5
但是注意浮点在处理十进制值时本质上是不准确的。
编辑:
当然对于负数,应该是i = (f * 100) - 0.5
...