【问题标题】:How to round double / float in vala?如何在vala中舍入双/浮动?
【发布时间】:2021-11-21 16:24:18
【问题描述】:

如何将var x = 0.10000000000000001 舍入为0.10

【问题讨论】:

  • 不能四舍五入到 0.10,因为不存在具有 恰好该值的双精度/浮点数。 0.100000000000000005551... 是最接近的选择。

标签: floating-point double rounding glib vala


【解决方案1】:

你真的不需要那个。
由于浮点数的精度有限,这两个值本质上是相同的值0.100000000000000005551115123126

你可以看到二进制表示herehere

也许您想显示截断值 - 在这种情况下,请使用您的编程语言的格式化函数,就像在 C# 中这样:

 Console.WriteLine(x.ToString("0.00"));

【讨论】:

  • 感谢您的回答。我确实要求有更好的视觉表现,但不是string。我所做的是将double 变量序列化为json"scale-factor" : 0.29999999999999999 感觉有点奇怪。
  • 好的,我明白了。我对json不熟悉,但是看看at this theme关于c#/json格式的介绍
  • 我认为这个问题更多地与编程语言有关,而不是 json。我希望有一个类似于Math.round (0.1234, 2) 的函数,它会导致0.1 或其他东西。我知道有一个math library,但我还没有找到我需要的。
  • 但是……不存在完全等于 0.1 的双数
【解决方案2】:

如果您将数据输出到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

Try it online!

【讨论】:

    【解决方案3】:

    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");
    }   
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-12
      • 2013-07-08
      • 1970-01-01
      • 2012-03-16
      • 2016-12-28
      • 2015-09-07
      • 1970-01-01
      • 2012-02-05
      相关资源
      最近更新 更多