22

同様の質問LonginFloat、なぜですか?ここでは私が探しているものには答えません。

C#標準では、longからfloatへの暗黙的な変換が可能です。ただし、フロートとして表されたときに2 ^ 24を超えると、その「値」が失われます。C#標準では、ロングからフロートへの変換では「精度」が失われる可能性がありますが、「マグニチュード」が失われることはないと明確に規定されています。

私の質問は
  1. 整数型に関して、「精度」と「大きさ」が意味するもの。3.333333と3.333329が計算に十分近いと見なされる可能性がある実数とは異なり、数値nは数値n + 1と完全に異なるわけではありません(つまり、精度プログラマーが何を望んでいるかによって異なります)。
  2. 長いから「静かに」価値を失う可能性があるため、longから微妙なバグへの招待をフロートさせる暗黙の変換を許可していません(C#プログラマーとして、私はコンパイラーがそのような問題から私を守るのに優れた仕事をすることに慣れています)

では、この変換を暗黙的に許可することで、C#言語設計チームの論理的根拠は何でしたか?longからfloatへの暗黙の変換を正当化するためにここで欠落しているのは何ですか?

4

5 に答える 5

13

これは良い質問です。実際には、次の暗黙の変換にも同じ問題が存在するため、この質問を一般化できます。

  • intfloat
  • uintfloat
  • longfloatあなたが尋ねている
  • ulongfloat
  • longdouble
  • ulongdouble

実際、すべての整数型(さらにはchar!!) には and への暗黙的な変換がfloatありdoubleます。ただし、上記の変換のみが精度の損失を引き起こします。注意すべきもう 1 つの興味深い点は、「なぜ decimal から double への暗黙的な変換がないのか」を説明するときに、C# 言語仕様に自己矛盾する引数があることです。

10 進数型は、浮動小数点型よりも精度が高くなりますが、範囲が狭くなります。したがって、浮動小数点型から 10 進数への変換でオーバーフロー例外が発生する可能性があり、 10 進数から浮動小数点型への変換で精度が失われる可能性があります。これらの理由から、浮動小数点型と decimal の間に暗黙的な変換は存在せず、明示的なキャストがなければ、同じ式で浮動小数点オペランドと小数オペランドを混在させることはできません。

「なぜこの決定が下されたのか」という質問は、エリック・リッパートのような人物が最もよく答えることができると思います. 私の最善の推測...これは、言語設計者がどちらか一方に進むことについて強い議論を持っていなかったものの1つであったため、言語設計者は(彼らが考えた)より良い代替案を選択しましたが、それは議論の余地があります. 彼らの弁護では、大きなlongfloatに変換すると、精度が失われますが、浮動小数点数の世界でその数値の最良の表現が得られます。これは、オーバーフローが発生する可能性がある場合に を変換するようなものではありません (整数値intは、bytebyteを表すことができます)、無関係な/間違った番号を取得します。それでも、私の意見ではdecimal、精度の損失を引き起こすこれらの他の変換がなければ、浮動小数点数への暗黙的な変換がない方が一貫していたでしょう。

于 2012-06-25T15:09:34.520 に答える
8

一般に、浮動小数点数は多くの数を正確に表すわけではありません。その性質上、それらは不正確であり、精度誤差の影響を受けます。浮動小数点の場合に常に当てはまることについて警告することは、実際には価値を追加しません。

于 2012-06-25T11:14:24.937 に答える
2
  1. 整数型に関して、「精度」と「大きさ」が意味するもの。3.333333 と 3.333329 が計算に十分近いと見なされる実数とは異なり (つまり、プログラマーが望む精度に応じて)、数値 n は数値 n+1 とはまったく異なりますか?

「精度」は、数字が運ぶことができる桁数を定義します。(簡単にするために)BCDでエンコードした場合、1バイトは2桁の10進数しか運ぶことができません。2 バイトが利用可能であるとしましょう。これらを使用して、0 ~ 9999 の数値を整数形式にエンコードするか、最後の桁が 10 進指数を意味する形式を定義できます。

次に、0-999 * (10^0 - 10^9) をエンコードできます

0 ~ 9999 の数値をエンコードする代わりに、999 000 000 000 までの数値をエンコードできるようになりました。ただし、整数形式から新しい形式に 9999 をキャストすると、9990 しか得られません。マグニチュード) ですが、精度が失われます。

double と float を使用すると、正確に表現できる次の値が得られます: (int = 32 ビット、long = 64 ビット、両方とも符号付き:)

int -> float -2^24 - 2^24

int -> すべての値を倍増

long -> float -2^24 - 2^24

long -> double -2^53 - 2^53

long から float への暗黙的な変換を許可していないのは、微妙なバグへの誘いです > long が「黙って」値を失うことにつながる可能性があります (C# プログラマーとして、私はコンパイラーに慣れています > そのような問題から私を守る優れた仕事をしています)

はい、サイレントバグが発生します。Compiler がこれらの問題を解決してくれると期待している場合は、忘れてください。あなたは自分の好きにしなさい。精度の低下を警告する言語を私は知りません。

そのようなバグの 1 つ: アリアン ロケット...

于 2012-06-25T10:09:38.577 に答える
1

さらに考えてみると、3 つの回答 (多かれ少なかれ同じことを指しています) はすべて、その「理由」の部分を正しく説明できるようです。

  1. float と long は両方とも数値型です
  2. float の範囲は long の範囲を保持するのに十分な大きさです

上記の 2 つの基準は、long から float への変換が暗黙的に行われる必要があることを示すのに十分だったと思います。

float は単精度であるため、long のすべての値を正確に表すことはできませんでした。したがって、彼らはそれを事実の陳述として基準に含めました。long から float への変換は「安全」です。結果の float は long 値を簡単に表すことができますが、精度が失われてコースから外れます。

さらに float から long への変換は暗黙的ではなく (float の範囲は long が保持できる範囲よりもはるかに大きいため)、これにより、このようなことが黙って許可されないようになります。

long lng = 16777217;
float flt = lng; //loses precision here
long lng2 = flt; //if permitted, would be 16777216 or 2^24
bool eq = lng == lng2;

long の値が失われるという問題は、変換された long を静かに取得できる場合にのみ発生しました。

私の理解を深めるのを手伝ってくれてありがとう。

于 2012-06-25T11:38:22.853 に答える
1

最大値は次のようlongに配置できますfloat

float.MaxValue ~= 3.402823+e38 
long.MaxValue ~= 9.223372+e18 

long64bit Integer型でですfloat32bit、コンピュータの処理方法float'sは とは異なりlong'sます。しかしfloat、精度を犠牲にしてより広い範囲が達成されます。

longよりもはるかに高い精度を持っていますが、浮動小数点数は10^18floatと比較して 10^38 の桁数が高くなっています。long

7 桁まで正確なasからlongへの暗黙的な変換を許可する間違いを犯したとは思いません。したがって、より精度が必要な場合は、いつでもor decimal`を使用できますfloatfloatdouble

Double-15 ~ 16 桁 (64 ビット)

Decimal-28 ~ 29 桁の有効数字 (128 ビット)

于 2012-06-25T06:31:44.213 に答える