2

私は最近 C# の学習を開始し、入力を華氏から摂氏に変換して元に戻す必要がある簡単な演習を作成しました。コードは単純で、これは私の努力です (ユーザーが数値入力を与えると思います):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class DegreeConversion
    {
        static void Main(string[] args)
        {
            Console.Write("Insert far -> ");
            float far = float.Parse(Console.ReadLine());
            float cel = (far - 32) / 9 * 5;
            Console.WriteLine(far   " degrees Fahrenheit is "   cel   " degrees Celsius");
            float far2 = cel * 9 / 5 + 32;
            Console.WriteLine(cel   " degrees Celsius is "   far2   " degrees Fahrenheit");
        }

    }
}

それは実行されましたが、華氏に戻るときに入力0で試してみると、-1.525879E-06 のような値が得られます。近似誤差、おそらくキャンセルについて考えました。以前のコードを少し変更しました。特に、これを変更しました

float far2 = cel * 9 / 5 + 32;

これに

float far2 = cel * 9 / 5;
float newFar = far2 + 32;

そして今、出力は0です!

この動作は、パフォーマンスを向上させるためにコードを再配置した C# コンパイラに関連していると思います。最初のコードはすべての操作を CPU レジスタに実装し、2 番目のコードはそれらをメモリに保存する必要があると思います。私は正しいですか?この場合、何が起こっているのか、近似がどのように機能するのか説明できますか?

前もって感謝します!

4

2 に答える 2

3

ここにはいくつかの問題があります。

  1. float、またはSystem.Singleその完全な名前を付けるには、単精度浮動小数点数です。これは、その精度が非常に限られていることを意味します。多くの操作では、わずかな丸め誤差が発生します (たとえば、-1.525879E-06: は 100 万分の 1 を少し上回っています)。

    double最初に(または)に切り替えSystem.Doubleます。特に指定しない限り、これがデフォルトの浮動小数点型です。

    2 番目にすべきことは、浮動小数点表現に固有の限られた精度を理解する (そして受け入れる) ことです。(たとえば、2 つの浮動小数点数が等しいかどうかを直接比較することはなく、絶対差が小さな値「イプシロン」よりも小さいことを確認します。 ここで、イプシロンはとMath.Abs(a - b) < epsilon のスケールに依存します。)ab

    最後に、すべてのコンピューター科学者が浮動小数点演算について知っておくべきことをお読みください。

  2. 9/5(および同様の) 整数として実行されます (つまり、切り捨てられます)。含まれる値はいずれも整数ではないためです。( ) を試してください9.0 / 5.0。(これは厳密には、最初の項の型が型 (your cel) を設定するより大きな式の一部であるためですが、これらの演算が浮動小数点であり、整数ではないことを明確にするために、キャリティ コード コードが追加されています。)

于 2013-09-22T09:28:52.093 に答える
2

これは単なる丸め誤差であり、浮動小数点計算を使用するときによく発生します。これは、一部の数値が 2 進数で正確に表現できないという事実の結果です (1/3 = 0.333333 などの繰り返し数値を考えてください)。

これを修正するには:

  1. float の代わりにdoubleorなどのより正確な数値型を使用します。decimal
  2. それを行った後でも、表示する小数点以下の桁数を制限する必要があります。

小数点以下の桁数を制限するには、 に表示する桁数を指定できますToString()

string numberToDisplay = far.ToString("n2"); 
// The "n2" means "format with 2 decimal places"
于 2013-09-22T09:26:43.523 に答える