6713


Decimal, Single と Double の違いについて違いおよび使い分け方を教えていただけませんか？


CC BY-SA 3.0
2015-02-18T20:47:53.537
6711
2015-02-19T11:50:18.367
2015-02-18T21:35:08.323
4236
5987
question
.net
Decimal, Single とDouble の違いについて


最大の違いは精度です。

  * `Single` 32ビット、仮数23ビット、指数8ビット
  * `Double` 64ビット、仮数52ビット、指数11ビット
  * `Decimal` 128ビット、仮数96ビット、指数5ビット=10^(-28～0)

上記のとおり`Decimal`は指数が10進なので、2進に起因する誤差が発生しません。なのでDBの10進表現や金融計算に利用されます。  
しかし`Single`と`Double`が.NET中間言語のネイティブ型であるのに対して、`Decimal`はカスタム構造体なのでパフォーマンスが悪いです。

対応ライブラリの面で言うと、多くの画像・3Dライブラリでは座標に最小サイズの`Single`を使用しています。また.NET4.6で導入される`System.Numerics.Vectors`も`Single`中心です。例外としてはWPFで`Double`が標準となっています。

一方`System.Math`や`System.Numerics.Complex`などの数学的な標準APIは`Double`がインターフェイスになっていることが多いです。これは精度(あるいはCPUの命令)を優先したためと思われます。

## 追記 .NETのプリミティブ型について

コメントで言及したので追記しますが、.NETには仮想機械でサポートされている[プリミティブ型](https://msdn.microsoft.com/ja-
jp/library/system.type.isprimitive%28v=vs.110%29.aspx)というものがあります。具体的には

  * 整数(`Byte`, `SByte`, `Int16`, `UInt16`, `Int32`, `UInt32`, `Int64`, `UInt64`)
  * 実数(`Single`, `Double`)
  * ポインタ(`IntPtr`, `UIntPtr`)
  * `Boolean`
  * `Char`

で、これらは中間言語(CIL)上でネイティブ数値型として扱われます。なのでC#やVB上でも演算は言語仕様の一部として扱われており[MSDNを参照しても一部の演算子が定義されていません](https://msdn.microsoft.com/ja-
jp/library/ff986405%28v=vs.110%29.aspx)。

一方`Decimal`は[共通言語仕様(CLS)のプリミティブ型](https://msdn.microsoft.com/ja-
jp/library/12a7a7h3%28v=vs.110%29.aspx#mt272)、つまり標準で入っているカスタム構造体という位置づけになります。これらはCILネイティブの型からUプリフィックス付の型と`SByte`を除外し、`Decimal`と`String`を加えたものです。ですので標準ライブラリを使用せずにビルドする場合でも`Decimal`を定義する必要はありません。(`String`は必要です)


CC BY-SA 3.0
2015-02-18T22:01:06.407
6713
2015-02-19T11:50:18.367
2020-06-17T08:14:45.997
-1
5750
6711
answer


pgrhoさんに補足ですがある程度の分量があるのでコメントでなく独立した回答とします。

パフォーマンス差について、.NET中間言語においては対等です。ただし実行する際にCPUがDecimal型をサポートしていない場合、エミュレーションライブラリを用いて計算を行うため圧倒的に遅くなります。具体的にはIntelプロセッサーはDecimal型をサポートしていません。これは32bitプロセッサにおいてInt64の計算が遅くなることと同じ原理です。

またSystem.Mathは.NET
1.0から存在しますが、当時のIntelプロセッサーではSingleに対してもDoubleに対しても80bit精度で計算が行われるという実情があったために、プログラミング界隈でも「とりあえずDoubleで計算しておけ」という風潮があったと記憶しています。System.Mathもそれを受け継いだ形と思われます。

System.Numerics.Vectorsについてはpgrhoさんの記述通りですが、加えて実行環境としてIntelプロセッサーとしてもレジスターサイズが128bitでありDouble精度ですと２変数しか同時に計算が行えずたいした効果を持ちません。そのためSingleが中心となっています。AVX（具体的には2011年に登場したSandy
Bridge）以降はレジスターサイズが256bitに拡張されましたが、命令がまだまだ足りない印象でした。その後AVX2などが登場していますので、状況が変わっているかもしれません。


CC BY-SA 3.0
2015-02-18T23:10:45.453
6714
2015-02-18T23:10:45.453
4236
6711
answer