【发布时间】:2021-11-21 16:24:18
【问题描述】:
如何将var x = 0.10000000000000001 舍入为0.10?
【问题讨论】:
-
不能四舍五入到 0.10,因为不存在具有 恰好该值的双精度/浮点数。 0.100000000000000005551... 是最接近的选择。
标签: floating-point double rounding glib vala
如何将var x = 0.10000000000000001 舍入为0.10?
【问题讨论】:
标签: floating-point double rounding glib vala
【讨论】:
string。我所做的是将double 变量序列化为json。 "scale-factor" : 0.29999999999999999 感觉有点奇怪。
Math.round (0.1234, 2) 的函数,它会导致0.1 或其他东西。我知道有一个math library,但我还没有找到我需要的。
如果您将数据输出到FileStream,您可以使用其方法printf(string, ...) 相应地格式化您的数据。这个方法其实就是C的大名鼎鼎的fprintf()。
因此,假设您将 JSON 数据写入 FileStream,您可以使用以下代码截断(技术上不等于舍入,但非常接近)您的双精度值:
FileStream output; // the FileStream you're actually outputting to
double x = 0.1000000000001;
output.printf ("{\"some_value\": %.2f}", x);
// result: {"some_value": 0.10}
这将保留两位小数,而不管它们的值如何(这意味着也将输出两个零)。
如果您需要有关格式字符串如何工作的更多信息,printf()'s documentation 非常准确,其中包含大量示例。
此外,您可以通过使用您的一个 cmets 中的示例对此进行测试来查看实际执行舍入:
// test code
double x = 2.999999999999d;
stdout.printf ("%.2f", x); // will print 3.00
【讨论】:
C 中的round() 函数舍入为整数,因此舍入到固定小数位数的常用方法是将结果相乘再除,例如round(x * 100)/100 保留两位小数。 Stack Overflow 上有一个很好的答案:How do I restrict a float value to only two places after the decimal point in C?
要理解的重要一点是 IEEE 734 浮点运算不是十进制运算。正如其他答案已经说明的那样,值 0.1 无法精确表示。请参阅下面示例中舍入 0.123 和 0.10000000000000001 的差异。
使用valac -X -lm example.vala 编译以下 Vala 代码,-X -lm 告诉编译器链接到 C 数学库:
void main () {
var x = 0.10000000000000001;
// printf style for serialization to fixed decimal places, outputs 0.10
// this is a good way to serialize to two fixed decimal places
print ("%.2f\n", x);
// common way of rounding in C, outputs 0.12 in this example,
// but read example afterwards where the result is not as you expect
var y = 0.1234;
double a = Math.round(y*100)/100;
print (@"$a\n");
// IEEE 754 floating point arithmetic isn't decimal arithmetic,
// this outputs 0.10000000000000001, which is the same as the input
double z = Math.round(x*100)/100;
print (@"$z\n");
}
【讨论】: