奇怪的“一半甚至”四舍五入用不同的语言

时间:2021-09-02 17:02:00

GNU bash, version 4.2.24:

GNU bash,版本4.2.24:

$> printf "%.0f, %.0f\n" 48.5 49.5
48, 50

Ruby 1.8.7

Ruby 1.8.7

> printf( "%.0f, %.0f\n", 48.5, 49.5 )
48, 50

Perl 5.12.4

Perl 5.12.4

$> perl -e 'printf( "%.0f, %.0f\n", 48.5, 49.5 )'
48, 50

gcc 4.5.3:

gcc 4.5.3:

> printf( "%.0f, %.0f\n", 48.5, 49.5 );
48, 50

GHC, version 7.0.4:

GHC,版本7.0.4:

> printf "%.0f, %.0f\n" 48.5 49.5
49, 50

Wikipedia says that this kind of rounding is called round half to even:

*说,这种舍入被称为圆形的一半甚至是:

This is the default rounding mode used in IEEE 754 computing functions and operators.

这是IEEE 754计算功能和运算符中使用的默认舍入模式。

Why is this rounding used by default in C, Perl, Ruby and bash, but not in Haskell?

为什么在C,Perl,Ruby和bash中默认使用这种舍入,而不是在Haskell中?

Is it some sort of tradition or standard? And if it is a standard, why it's used by those languages and not used by Haskell? What is a point of rounding half to even?

它是某种传统还是标准?如果它是一个标准,为什么它被这些语言使用而不被Haskell使用?什么是四舍五入到均匀的点?

3 个解决方案

#1


11  

GHCi> round 48.5
48
GHCi> round 49.5
50

The only difference is that printf isn't using round — presumably because it has to be able to round to more than just whole integers. I don't think IEEE 754 specifies anything about how to implement printf-style formatting functions, just rounding, which Haskell does correctly.

唯一的区别是printf没有使用round - 大概是因为它必须能够舍入到不仅仅是整数。我不认为IEEE 754指定了关于如何实现printf样式格式化函数的任何内容,只是舍入,Haskell正确执行。

It would probably be best if printf was consistent with round and other languages' implementations, but I don't think it's really a big deal.

如果printf与圆形和其他语言的实现一致,那可能是最好的,但我认为这不是一个大问题。

#2


6  

"Round to even" is the default for use with IEEE 754. Haskell should probably switch to using it in printf for consistency reasons. The relevant line of code is in GHC.Float

“Round to even”是与IEEE 754一起使用的默认值。为了保持一致性,Haskell可能应该切换到在printf中使用它。相关的代码行在GHC.Float中

f 0 (x:_)  = (if x >= b2 then 1 else 0, [])

So, if someone wants to fix it, they can. As ehird points out, this would just make the roundTo function being used by printf consistent with round although I'm not sure what other code this change would break.

所以,如果有人想要解决它,他们可以。正如ehird指出的那样,这只会让printf使用roundTo函数与round一致,尽管我不确定这个改变会破坏什么其他代码。

EDIT: a previous version of this answer got the location of the rounding code wrong. The only significant difference between the two implementations is if they are hardcoded to use base 10.

编辑:此答案的先前版本得到了舍入代码的位置错误。两种实现之间唯一的显着差异是它们是否被硬编码以使用基数10。

#3


2  

I can't say for sure, but this probably has to do with the fact that this type of rounding is commonly used in accounting functions, as this is also known as Banker's rounding. If you look further at the Wikipedia article on rounding, you'll also notice this is default in IEEE 754, so likely Haskell isn't following that standard.

我不能肯定地说,但这可能与这种类型的舍入常用于会计功能这一事实有关,因为这也称为银行家的舍入。如果你进一步看*关于舍入的文章,你也会注意到这是IEEE 754中的默认值,所以很可能Haskell没有遵循该标准。

#1


11  

GHCi> round 48.5
48
GHCi> round 49.5
50

The only difference is that printf isn't using round — presumably because it has to be able to round to more than just whole integers. I don't think IEEE 754 specifies anything about how to implement printf-style formatting functions, just rounding, which Haskell does correctly.

唯一的区别是printf没有使用round - 大概是因为它必须能够舍入到不仅仅是整数。我不认为IEEE 754指定了关于如何实现printf样式格式化函数的任何内容,只是舍入,Haskell正确执行。

It would probably be best if printf was consistent with round and other languages' implementations, but I don't think it's really a big deal.

如果printf与圆形和其他语言的实现一致,那可能是最好的,但我认为这不是一个大问题。

#2


6  

"Round to even" is the default for use with IEEE 754. Haskell should probably switch to using it in printf for consistency reasons. The relevant line of code is in GHC.Float

“Round to even”是与IEEE 754一起使用的默认值。为了保持一致性,Haskell可能应该切换到在printf中使用它。相关的代码行在GHC.Float中

f 0 (x:_)  = (if x >= b2 then 1 else 0, [])

So, if someone wants to fix it, they can. As ehird points out, this would just make the roundTo function being used by printf consistent with round although I'm not sure what other code this change would break.

所以,如果有人想要解决它,他们可以。正如ehird指出的那样,这只会让printf使用roundTo函数与round一致,尽管我不确定这个改变会破坏什么其他代码。

EDIT: a previous version of this answer got the location of the rounding code wrong. The only significant difference between the two implementations is if they are hardcoded to use base 10.

编辑:此答案的先前版本得到了舍入代码的位置错误。两种实现之间唯一的显着差异是它们是否被硬编码以使用基数10。

#3


2  

I can't say for sure, but this probably has to do with the fact that this type of rounding is commonly used in accounting functions, as this is also known as Banker's rounding. If you look further at the Wikipedia article on rounding, you'll also notice this is default in IEEE 754, so likely Haskell isn't following that standard.

我不能肯定地说,但这可能与这种类型的舍入常用于会计功能这一事实有关,因为这也称为银行家的舍入。如果你进一步看*关于舍入的文章,你也会注意到这是IEEE 754中的默认值,所以很可能Haskell没有遵循该标准。