整数から単一への変換が精度を失う場合がある


27

拡大コンバージョンとオプションストリクトオンに関するマイクロソフトの記事を読んでいとき

次の変換は精度を失う可能性があります。

  • 整数から単一
  • ロングからシングルまたはダブル
  • 10進数からシングルまたはダブル

ただし、これらの変換では情報や規模は失われません。

..しかし、データ型に関する別の記事によると、

  • 整数型は-2.147.483.648から2.147.483.647まで保存でき、

  • シングルタイプから保存できます

    • 正の数の場合は1,401298E-45から3,4028235E + 38まで、
    • 負の数の場合は-3,4028235E + 38から-1,401298E-45

..そのため、SingleはIntegerよりもはるかに多くの数値を格納できます。どのような状況で整数から単一への変換が精度を失う可能性があるのか​​理解できませんでした。誰か説明してくれませんか?

回答:


87

シングルは整数よりもはるかに多くの数値を格納できます

いいえ、できません。両方SingleInteger32ビットであり、その両方が格納できることを意味正確に同じ数、すなわち2量32 = 4294967296異なる番号。

以来範囲のがSingleより明らかに大きい場合、それは(理由から直ちに明らかである鳩の巣原理それが)おそらくすることができない、その範囲内のすべての数を表します。

範囲ためInteger正確両方その数値の最大量と同じサイズであるIntegerSingle表現することができるが、Singleおそらくの範囲内のすべての数値を表すことができないことは明らかであり、また、その範囲外の数値を表すことができますInteger

Integerで表すことができない数値がいくつかある場合Single、からIntegerに変換するにSingle 情報を失うことができる必要あります。


3
この偉大な説明のために1 、なぜそれが問題が実際にいたにも関わらず、ケースなければならないとき、それが起こる(「どのような状況にある」)...
doubleYou

21
@doubleYou:4294967296 Integerの4261412864 (99.2%)はとして表すことができないSingleため、「when」は「ほとんど常に」です。
イェルクWミッターク

2
より正確にしたい場合は、Single4,278,190,079の異なる数値のみを表すことができます。Single値があれば数を表し、記憶された指数は、255 * 2 ^ 24が存在することを意味し、255ではない場合にのみSingle番号を示し、sは。これらのうち、2つは同じ数(つまり、ゼロ)を表し、他のすべては異なる数を表します。
20:23の

10
en.wikipedia.org/wiki/Single-precision_floating-point_formatは、IEEE754 binary32の制限をうまく説明しています。[-16777216,16777216](2 ^ 24 = 仮数幅)の整数は正確に表現できます。大きい数値は、その大きさに応じて、2、4、8、...の最も近い倍数に丸められます。
ピーターコーデス

14
「これは、両方がまったく同じ量の数値を格納できることを意味します」—それは意味しませ。両方のタイプが正確に同じ数の各番号を保存する方法を持っている場合にのみ意味します。そして、これはそうではありません。たとえば、Singleゼロを格納する2つの方法があります。したがってSingle、実際には、より少ない個別の数値を表すことができIntegerます。
コンラッドルドルフ

28

浮動小数点型(SingleやDoubleなど)は、メモリ内で符号、仮数、指数で表されます。科学的記法と考えてください:

Sign*Mantissa*Base^Exponent

予想どおり、ベース2を使用します。無限大とNaNを表すことを可能にする他の調整があり、指数がオフセットされます(それに戻ります)。 。詳細については、その表現と操作をカバーする標準IEEE 754を探してください。

ここでは、2進数の「仮数」と、小数点を配置する場所を示す「指数」と考えることができます。


シングルの場合、彼のサインに1ビット、指数に8ビット、仮数に23ビットがあります。

ここで重要なのは、最上位の桁から仮数を格納することです。左側のゼロはすべて関係ないことに注意してください。そして、バイナリで作業していることを考えると、最も重要な数字は1※であることがわかります。それはわかっているので、保存する必要はありません。その略記のおかげで、仮数の有効範囲は24ビットです。

※:保存している数字がゼロでない限り。そのために、すべてのビットをゼロに設定します。ただし、これを説明のもとで解釈しようとすると、2 ^ 24(暗黙の1)に1(2のべき乗0)を掛けたものになります。したがって、それを修正するために、指数ゼロは特別な値です。指数に無限大とNaNを格納する特別な値もあります。

指数オフセットに従って-特別な値を避けることとは別に-オフセットを持つことで、指数の符号を必要とせずに、仮数の開始前または終了後に小数点を配置できます。


これは、大きな数値の場合、浮動小数点型は仮数の末尾を超えて小数点を置くことを意味します。

仮数は24ビットの数値であることに注意してください。25ビットの数値を表すことはありません...余分なビットはありません。したがって、シングルは2 ^ 24と2 ^ 24 + 1を区別できません(これらは最初の25ビット数であり、シングルでは表されない最後のビットで異なります)。

したがって、整数の場合、単一の範囲は-2 ^ 24〜2 ^ 24です。そして、1を2 ^ 24に追加しようとすると、2 ^ 24になります(タイプに関する限り、2 ^ 24と2 ^ 24 + 1は同じ値です)。オンラインでお試しください。これが、整数から単一に変換するときに情報の損失がある理由です。また、これは、シングルまたはダブルを使用するループが、気付かないうちに実際に無限ループになる可能性がある理由でもあります。


これは、仮数の暗黙的な先行1ビットの完全な説明ではありません。バイアスれた指数フィールドが非ゼロであることを暗示していますを含む+-0.0非正規(別名非正規)には、0その仮数の先頭ビットがあります。単純に0.0完全に特殊なケースを考えるように単純化できると思いますが、0.0実際には他のサブノーマルと同じエンコード規則に従います。
ピーターコーデス

25

からに変換するIntegerSingle精度が失われる場合がある実際の例を次に示します。

このSingle型は、-16777216から16777216までのすべての整数を格納できますが、この範囲外のすべての整数を格納することはできません。たとえば、16777217という数値を格納することはできません。そのため、16777216より大きい奇数を格納することはできません。

Windows PowerShellを使用して、Integerからに変換した場合の結果を確認できますSingle

PS C:\Users\tanne> [int][float]16777213
16777213
PS C:\Users\tanne> [int][float]16777214
16777214
PS C:\Users\tanne> [int][float]16777215
16777215
PS C:\Users\tanne> [int][float]16777216
16777216
PS C:\Users\tanne> [int][float]16777217
16777216
PS C:\Users\tanne> [int][float]16777218
16777218
PS C:\Users\tanne> [int][float]16777219
16777220

16777217は16777216に切り捨てられ、16777219は16777220に切り上げられたことに注意してください。


4
そして、マグニチュードが増加するにつれて、最も近い表現可能な間の距離はfloat、べき乗として増加し続けます。 en.wikipedia.org/wiki/...
ピーター・コルド

12

浮動小数点型は、物理学の「科学表記法」に似ています。数値は、符号ビット、指数(乗数)、および仮数(有効数字)に分割されます。したがって、値の大きさが大きくなると、ステップサイズも大きくなります。

単精度浮動小数点には23の仮数ビットがありますが、「暗黙の1」があるため、仮数は事実上24ビットです。したがって、最大2 24の大きさの整数はすべて、単精度浮動小数点で正確に表現できます。

その上で、連続してより少ない数を表すことができます。

  • 2 24から2 25までは、偶数のみを表現できます。
  • 2 25から2 26までは、4の倍数のみを表すことができます。
  • 2 26から2 27までは、8の倍数のみを表すことができます。
  • 2 27から2 28までは、16の倍数のみを表すことができます
  • 2 28から2 29までは、32の倍数のみを表すことができます
  • 2 29から2 30までは、64の倍数のみを表すことができます
  • 2 30から2 31までは、128の倍数しか表現できません。

したがって、2 32の可能な32ビット符号付き整数値のうち、2 *(2 24 + 7 * 2 23)= 9 * 2 24のみが単精度浮動小数点で表現できます。これは全体の3.515625%です。


8

単精度フロートの精度は24ビットです。それ以上の値は、最も近い24ビットの数値に丸められます。10進数の科学表記で理解する方が簡単かもしれませんが、実際の浮動小数点はバイナリを使用することに注意してください。

5桁のメモリがあるとします。通常の符号なし整数のようなものを使用することを選択できます。0から99999の間の任意の数値を使用できます。より大きな数値を表現したい場合は、科学表記法を使用し、2桁を指数に割り当てることができます。 0から9.99 x 10 99までの範囲で表現できるようになりました。

ただし、正確に表すことができる最大数は999になりました。12345を表そうとすると、1.23 x 10 4または1.24 x 10 4を得ることができますが、その間の数字を表すことはできません。十分な数字がありません。


3
10進数を使用するとわかりやすくなりますが、最後の段落は少し誤解を招く可能性があります。実際に、999を超える数値表すことができ、例では次のようになります。12300は1.23 x 10 <sup> 4 <sup >。あなたが言っているのは、その数から始まってギャップがあるということです。少し言い換えていただけますか?
ファビオはモニカを
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.