283

ドキュメントによると、このdecimal.Roundメソッドは、ほとんどのアプリケーションでは一般的ではない偶数に丸めるアルゴリズムを使用します。そのため、私は常に、より自然な四捨五入アルゴリズムを実行するカスタム関数を作成することになります。

public static decimal RoundHalfUp(this decimal d, int decimals)
{
    if (decimals < 0)
    {
        throw new ArgumentException("The decimals must be non-negative", 
            "decimals");
    }

    decimal multiplier = (decimal)Math.Pow(10, decimals);
    decimal number = d * multiplier;

    if (decimal.Truncate(number) < number)
    {
        number += 0.5m;
    }
    return decimal.Round(number) / multiplier;
}

このフレームワーク設計の決定の背後にある理由を知っている人はいますか?

フレームワークにラウンド ハーフアップ アルゴリズムの組み込み実装はありますか? または、管理されていない Windows API でしょうか。

decimal.Round(2.5m, 0)結果として 3 を期待しているのに 2 になると単純に書くと、初心者にとって誤解を招く可能性があります。

4

5 に答える 5

447

バンカーのアルゴリズム (別名round half to even ) が適切な選択である理由を含む他の回答は、非常に正しいものです。ほとんどの合理的な分布では、ゼロから離れた半分の方法ほど、負または正のバイアスの影響を受けません。

しかし、問題は、.NET が Banker の実際の丸めをデフォルトとして使用する理由でした。その答えは、Microsoft がIEEE 754標準に従っているということです。これは、MSDN の Math.Roundの備考欄にも記載されています。

MidpointRoundingまた、.NET は、列挙型を提供することにより、IEEE によって指定された代替方法をサポートしていることにも注意してください。もちろん、同点を解決するためのより多くの代替手段を提供することもできましたが、IEEE 標準を満たすことだけを選択しました。

于 2011-07-03T09:09:41.327 に答える
206

おそらくそれはより良いアルゴリズムだからです。実行される多くの丸めの過程で、すべての .5 が均等に上下に切り上げられることを平均化します。これにより、たとえば丸められた数値を追加する場合に、実際の結果をより正確に見積もることができます。一部の人が期待するものではないかもしれませんが、それはおそらくより正しいことだと思います.

于 2008-11-22T19:57:14.757 に答える
89

「マイクロソフトの設計者がなぜこれをデフォルトに選んだのか」という質問には答えられませんが、余分な機能は不要であることを指摘しておきたいと思います。

Math.Round次を指定できますMidpointRounding

  • ToEven - 数値が他の 2 つの数値の中間にある場合、最も近い偶数に丸められます。
  • AwayFromZero - 数値が他の 2 つの数値の中間にある場合、ゼロから離れた最も近い数値に丸められます。
于 2008-11-22T19:59:54.330 に答える
22

小数は主にお金に使用されます。銀行の丸めは、お金を扱う場合に一般的です。または、あなたは言うことができます。

10 進数型を必要とするのはほとんど銀行家です。したがって、「バンカーの丸め」を行います</p>

バンカーの丸めには、次の場合に平均して同じ結果が得られるという利点があります。

  • 合計する前に一連の「請求明細」を丸めます。
  • またはそれらを合計してから合計を四捨五入します

合計する前に四捨五入することで、コンピューターが登場する前の時代に多くの作業を節約できました。

(英国では、10 進法の銀行は 0.5 ペンスを扱っていませんでしたが、何年もの間、まだ 0.5 ペンスの硬貨があり、ショップでは価格が 0.5 ペンスで終わることがよくありました。そのため、多くの丸めが行われます)

于 2010-01-22T12:58:04.503 に答える