2012-03-22 5 views
12

GNUのbashのを丸め、バージョン4.2.24:奇妙な "半分でもする" とは、異なる言語で

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

のRuby 1.8.7

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

のPerl 5.12.4

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

GCC 4.5.3:

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

GHC、バージョン7.0.4:

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

ウィキペディアは丸めのこの種のround half to evenと呼ばれていることを述べている:

これは、IEEE 754の演算関数と演算子で使用されるデフォルトの丸めモードです。

C、Perl、Ruby、bashではこの丸めがデフォルトで使用されますが、Haskellではこの丸めが使用されないのはなぜですか?それは、伝統や標準のいくつかの並べ替え

ですか?それが標準の場合、なぜそれらの言語で使用され、Haskellでは使用されていないのですか?半分を丸める点は何ですか?

+4

を使用するようにハードコードされている場合は2つの実装の間でのみ有意差があります。これはIEEE 754標準の一部です。 –

+0

@Keith Irwin、私は彼がどの標準を知りたかったと思う。うまくいけば関連するリンクでそれを答えとして投稿してみませんか? – ikegami

+2

ドミトリー:質問に「IEEE 754」と具体的に言及しています。これが基準です。 – Gabe

答えて

11
GHCi> round 48.5 
48 
GHCi> round 49.5 
50 

唯一の違いは、printfroundを使用していないことです。私は、IEEE 754が、Haskellが正しく機能するように、printf形式の書式設定関数を実装する方法について何も指定していないと考えています。

printfroundと他の言語の実装と一貫しているのがおそらく最も良いでしょうが、それは本当に大きな問題ではないと思います。

+0

printf形式の書式関数は、固定小数点の10進形式に変換します。 IEEE 754では、現在の丸めモードで変換が行われることが推奨されています。現在の丸めモードに関係なく、変換のために最も近い偶数を使用して、多くの言語/プラットフォームが2012年の時点でこの問題を解決していることに注意してください。 –

+5

@PascalCuoq:情報をありがとう!しかし、 'printf'は純粋な関数でなければならないので、Haskellは単にその勧告に従うことができません。丸めモードをパラメータとして使用するか、その情報が利用可能なコンテキスト(モナドなど)で動作する必要があります。 – ehird

+0

良い点。 IEEE 754のような言語に依存しない標準は、あいまいさを多く残し、適応するのに不便かもしれません。他の比較的似たような状況は、命令型浮動小数点プログラムのHoare論理検証です。ここでは、プログラムの状態と浮動小数点関数の引数の追加部分として丸めモードを考えることは避けたいのですが、実行時にそれを変更するプログラムを処理します。 –

2

私は確かに言うことはできませんが、これはおそらくこれもバンカーの丸めとして知られているように丸めのこのタイプは、一般的に、アカウンティング機能で使用されているという事実に関係しています。さらに、Wikipediaの四捨五入の記事を見ると、IEEE 754ではこれがデフォルトであることに気付くでしょう。したがって、Haskellはその標準に準拠していない可能性があります。おそらくそれだけで全体の整数以上に丸めることができなければならないので -

+1

リンクされたWikiの記事では、「この用語の丸め方が銀行の標準であったとすると、その証拠は非常に見つけることが困難であることが判明しています。委員会の報告「ユーロ導入と通貨量の丸め」[16]は、これまで銀行業務の丸めに標準的なアプローチがなかったことを示唆しており、「中間金額」を増やすべきであると規定している。したがって、銀行家は銀行家の丸めを使用しません。 –

+0

@ A.H。実際、彼らは依然として限られた範囲でバンカーの丸めを使用しています。私は銀行グループのために働いていたように、知識でそれを述べることができます。 –

+0

私は、金融機関でも使用される丸めの知識を持っています。しかし、米国ではありません。しかし、ここの観客も国際的です。 –

6

「ラウンドさえする」Haskellはおそらく一貫性の理由からprintfでそれを使用するように切り替える必要がありますIEEE 754で使用するデフォルトです。コードの該当する行は GHC.Float

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

誰かがそれを修正したいのであれば、彼らができるです。他人が指摘しているように、これはprintfroundと一貫して使用するようにしていますが、この変更がどのようなコードを改悪するのかは分かりません。

EDIT:この答えの前のバージョンが間違って丸めコードの場所を得ました。彼らは私はあなたがちょうどあなた自身の質問に答えだと思うベース10

+2

私はそれが正しいコード行だとは思わない。 'Text.Printf'は' Text'ではなく 'String'で動作します。 – ehird

+0

@ehird Text.Printfは 'dfmt'というヘルパー関数を呼び出します。これはNumericから' showFFloat'を呼び出す 'dfmt'という別のヘルパーを呼び出します。実装に依存しているのですが、私はこの質問に答えたときにGHCコードを 'Data.Text'モジュールに追い込んだと思っていました。今度は二重チェックが必要です。 –

+0

は正しいと思われます:GHC 7.4.1では、 'formatRealFloat'によって呼び出された' roundTo'関数が 'Data.Text 'の呼び出しではなく、そのファイルに含まれています。等。それは同じことをしますが、基本認識です –

関連する問題