【发布时间】:2013-10-02 19:05:18
【问题描述】:
我需要将具有系统精度的浮点数转换为具有指定精度(例如 3 位小数)的浮点数以用于打印输出。 fprintf 函数不足以解决此问题,因为它无法正确舍入某些数字。我尝试过的所有其他解决方案都失败了,因为当我转换回浮点数时,它们都重新引入了不希望的精度。例如:
float xf_round1_f(float input, int prec) {
printf("%f\t",input);
int trunc = round(input * pow(10, prec));
printf("%f\t",(float)trunc);
input=(float)trunc / pow(10, prec);
printf("%f\n",input);
return (input);
}
此函数将输入、截断的整数和输出打印到每一行,对于一些应该截断到小数点后 3 位的数字,结果如下所示:
49.975002 49975.000000 49.974998
49.980000 49980.000000 49.980000
49.985001 49985.000000 49.985001
49.990002 49990.000000 49.990002
49.995003 49995.000000 49.994999
50.000000 50000.000000 50.000000
您可以看到第二步按预期工作 - 即使“trunc”被强制转换为浮点数以进行打印 - 但一旦我将其转换回浮点数,精度就会返回。第 1 行和第 6 行说明问题案例。
肯定有办法解决这个问题——即使第一行的结果仍然是 49.975002,格式化打印也会产生预期的效果,但在这种情况下确实存在问题。
有什么解决办法吗?
【问题讨论】:
-
这是二进制浮点无法避免的,抱歉。
-
@Eric 抱歉一发布就删除了它,因为它也没有回答问题:-)。
-
通常这种情况下的方法——例如货币金额,是使用整数类型并将其转换为固定精度以用于显示目的。例如。对于货币,您可以使用 int32_t 美分。一些编程语言(例如 COBOL)有特定的类型来处理这个问题。根本问题是 5 不会像 3 不会进入 10 那样进入 2,所以任何十进制数都是二进制的无限循环扩展。
-
@JWDN:您的问题可能被否决了,因为您仍然没有准确地指定问题,您没有正确使用浮点,并且您可能不应该使用它。如果您想保留十进制数字,还有其他方法可以进行算术运算。浮点专为数学、科学和工程计算而设计,具有大动态范围和良好的数学特性。您将其用于与设计目的不同的目的,因此您当然会遇到问题。您接受的答案是杂牌。
标签: c linux floating-point rounding