如何在 Haskell 中使用 printf 像在 C 中一样对浮点数进行四舍五入?

How to round float numbers in Haskell just like in C using printf?

提问人:eightShirt 提问时间:6/30/2023 最后编辑:eightShirt 更新时间:7/1/2023 访问量:121

问:

我有一个简单的代码来读取浮点数并用小数点后六位打印它。

我的 C 代码可以工作,我想在不安装任何额外库的情况下与 Haskell 语言相等。

我的解决方案在 C 和 Haskell 中非常简单:

C:

#include <stdio.h>
int main() {
    float n = 123.141568;
    printf("%.6f\n", n); // 123.141571
    return 0;
}

哈斯克尔:

import Text.Printf (printf)
main = do
  let n = 123.141568 :: Float
  printf "%.6f\n" n -- 123.141570

这些代码适用于大多数数字,但有一些不同的结果。例如,当 C 程序输出并且 Haskell 程序打印时。如果我在 Haskell 中从 更改为 ,结果是 .n = 123.141568123.141571123.141570FloatDouble123.141568

我的目标是使我的Haskell代码等于C。我意识到即使在两种语言中使用 printf 的舍入方法也不同,但我不知道它是如何发生的。

我尝试制作自定义舍入函数,但结果与(在上面的示例中)和()相同:Float123.141570Double123.141568

customRound x n = fromIntegral (round (x * 10^n)) / 10^n

关于如何解决这个问题的任何想法?

提前致谢!

Haskell 浮点 printf 精确 数字格式

评论

4赞 n. m. could be an AI 6/30/2023
32 位包含大约 7 位十进制数字。 不能完全表示为 。最接近的确切可表示数字是 123.141571044921875。如果你使用典型的 C,printf 将完全打印它(即使 C 标准没有指定),而 Haskell printf 将打印 .无论如何,小数点后第 5 位以外的所有内容都是噪音,但如果您需要它,获取它的最简单方法就是 .float123.141568float%.15f123.141570000000000printf "%.6f\n" $ float2double n
2赞 chux - Reinstate Monica 6/30/2023
n = 123.141568在 或 中不完全表示。@eightShirt,发布一个最小的可重现示例,以清楚地展示您的代码。floatdoublelong double
0赞 eightShirt 7/1/2023
谢谢@n.m.willseey'allonReddit,您使用GHC的解决方案。浮动(float2Double)对我来说已经足够了。
0赞 chux - Reinstate Monica 7/6/2023
@eightShirt,鉴于“用小数点后六位打印”,我建议你的目标放错了地方。浮点数应该“用六个有效小数位打印它”。使用或float nprintf("%.5e\n", n);printf("%.6g\n", n);

答: 暂无答案