• ベストアンサー

C#の型について(doubleとdecimal)

C#でのdoubleとdecimalについて、 ヘルプを読むと丸め誤差の処理が異なっているとの事ですが、 どちらがより正確な計算結果が得られる方なのでしょうか? よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

>Mathクラスのメソッドは正確性を求めるものではないということでしょうか? Mathクラスのインプリメントについて、あーだこーだ言えるような者ではないのですが、 私見を述べると、 そうした、算術演算ライブラリは、適当な計算精度があることがわかっていて使えば問題ないものです。(もしそれで充分でないなら、別に方法を考える必要がありますが) そうした精度とそのためのコスト(メモリやら計算に要する時間とか)は、トレードオフですので、いつも大きな精度が必要というわけではないことを考えるべきです。(例えば、隣町の方向を計算するのに、宇宙旅行程度の計算精度は必要ありません) 多くの算術演算ライブラリでdoubleの精度になっているのは、1つには規格ということもありますが、FPUというハードウェアで計算できるということがあります。そういうものを使わない計算は、結局プログラムにより求めることになり、CPUの負荷が増します。 >C#にもBigDecimalのようなものがあればなと思いました。 BigIntegerクラスが公開されています。 http://www.codeproject.com/csharp/biginteger.asp BigDecimal は、BigIntegerがあれば、実現あるいは代用ができます。

nihon_no_samurai
質問者

お礼

ありがとうございます。勉強になりました!

その他の回答 (2)

  • neuron-x
  • ベストアンサー率52% (139/266)
回答No.2

decimalの方が正確な計算ができます。double型は誤差が発生する場合があります。正しく計算する場合は、全てdecimalで計算します。計算途中のどこかでdoubleなどを混ぜると、その時点で誤差が発生する可能性があります。 ちなみにJavaでもdoubleは誤差が発生します。そのためBigDecimalクラス(C#のdecimalよりも有効桁数が多い)を使って計算を行います。

nihon_no_samurai
質問者

お礼

C#にもBigDecimalのようなものがあればなと思いました。 どうもありがとうございます。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

decimal型は、内部的には整数(と小数点位置)で数を表すので、有効範囲内では誤差無しです double型は、内部的に2進小数(と指数部)で数を表すので、2進小数表現にした場合に誤差が生じる(例えば10進の0.1が、2進小数で正確に表現できない)場合があります。

nihon_no_samurai
質問者

補足

ありがとうございます。 doubleよりdecimalのほうが誤差が無いということですが、 Mathクラスにはdoubleを返すものが多いようです。 Mathクラスのメソッドは正確性を求めるものではないということでしょうか?

関連するQ&A

  • 型「double」「decimal」「float」について教えて下さい

    型「double」「decimal」「float」について教えて下さい。 VB2010とSQL Server 2008 R2 で開発を行っている初心者です。 単価が銭単位(例えば0.01円=1銭)の商品の金額計算を するとき、最初に変数を「Double」を使って、最後に小数点以下 のまるめ処理を行っていたところおかしな金額計算されてしまい ました。 具体的には、 Dim intSuryo As Integer Dim dblTanka As Double Dim dblKingaku As Double Dim marumeKingaku As Double If tbSuryoArray(i).Text <> Nothing Then If tbTankaArray(i).Text <> Nothing Then dblKingaku = 0 dblKingaku = intSuryo * dblTanka Select Case intMarumeKubun Case 1 : marumeKingaku = Math.Truncate(dblKingaku) '切り捨て Case 2 : marumeKingaku = Math.Round(dblKingaku, 0, MidpointRounding.AwayFromZero) '四捨五入 Case 3 : marumeKingaku = Math.Ceiling(dblKingaku) '切り上げ End Select のコードを書いて計算すると、(単価)4.31×(数量)5000 の計算が、 本来「21550」にならなければいけないのに「21549」になってしまいます。 いろいろ調べてみた結果、変数の型を「Double」にするのがいけなくて、 「Decimal」にすると誤差がなくなるということで、変数をすべて「Decimal」 に直したところ、誤差の現象がでなくなったので問題は解決しました。 問題がもうひとつおきました。 データベースの単価の型も変える必要があるかと思い、 SQL Server内のテーブルの単価のカラムを「float」から「decimal(18,0)」に 変えたところ、既に格納されている値がすべて整数に変わってしまいました。 何やらわけがわからず戸惑っていますが、同じ「Decimal」でもVBとSQL Server では利用方法が異なるのでしょうか? またVBでの「Double」と「Decimal」の使い分け、 SQL Serverでの「float」と「decimal」の使い分け、 について教えて下さい。 よろしくお願いします。

  • 独習C# 型

    独習C#のP85で質問です。 ローン返済額を計算するプログラムですが、最後の Console.WriteLine("Payment is { 0:C} ", Payment); のところで以下エラーがでます。 「入力文字の形式が正しくありません。」 本の通り記述しているのですが、何ででしょうか? --以下コード-- private void button8_Click(object sender, EventArgs e) { decimal Principal; //元金 decimal IntRate;  //decimal型の金利、たとえば0.075 decimal PayPerYear;//年間の支払い回数 decimal NumYears; //返済期間の年数 decimal Payment; //1回当たりの返済額 decimal numer, denom;//Pow()メソッド用の基数と指数 double b, g; Principal = 1500000.0m; IntRate = 0.075m; PayPerYear = 12.0m; NumYears = 5.0m; numer = IntRate * Principal / PayPerYear; g = (double) - (PayPerYear * NumYears); b = (double) (IntRate / PayPerYear) + 1; denom = 1 - (decimal) Math.Pow(b, g); Payment = numer / denom; Console.WriteLine("Payment is { 0:C} ", Payment); }

  • VB.net Double と Decimal の違い?

    VB.NETで開発しています 元々はC言語で開発してましたが、最近VB.NETをしています で、以前誰かが作ったプログラムをデバッグしているんですが、その中に Double や Decimal が混じっています どちらも 浮動小数点 と思うんですが 違いがいまいちわかりません 混じらせる利点ってないと思うんですが、どうなんでしょう? 有効桁数が違うとかだけだったら 簡単なんですが・・

  • C# 巨大な文字列の計算をさせたい

    お世話になります。 C#にて、文字列からなる計算式 string s = "(3270+(5*4))/7"; のようなものを計算して 値を返す処理を作成したいと思っています。 http://dobon.net/vb/dotnet/programing/eval.html ↑上記のサイト様から、DataTable.Computeで 求める方法を参考にしたのですが、戻り値を decimalで受けたいのですが、decimalで取得することができません。 doubleでは取得できますが、decimalでcastしようと すると、InvalidCastExceptionが発生します。 string exp = "(1+6)*5/(7-4)"; //式を計算する System.Data.DataTable dt = new System.Data.DataTable(); decimal result = (decimal)dt.Compute(exp, "");        ↑この行で発生 要は、intやdoubleでは収まらない巨大な桁を持つ文字列の 計算をさせたいのですが、どうすればよいでしょうか。 よろしくお願いいたします。

  • COBOLで作成されたPACKED-DECIMAL型のデータをJavaで利用する場合の型は?

    COBOLで作成されたデータを受け取り、javaで処理する必要があるのですが、データの中にPACKED-DECIMALの形式の項目が存在します。 これは、double型で処理すれば問題ないのでしょうか? お手数ですが、よろしくお願いします。

    • ベストアンサー
    • Java
  • C#のdecimal型について

    C#のdecimal型について C#のdecima;型の変数に色々な値を代入して,バイナリファイルに出力する。 バイナリ出力ファイルを16進ダンプする。 これらのデータを観ると 16バイト目:符号(00:プラス、80:マイナス) 15バイト目:小数点以下の桁数 1~12バイト目:整数を逆転表示 f3 e0 01 00 00 00 00 00 00 00 00 00 00 00 03 00 123.123 123123 = x'01e0f3' なので逆転したf3 e0 01 となる とわかる。  ところで質問ですが、13、14バイト目のデータは何に使用しているのでしょうか。 わかっている方がおりましたら、教えて下さい。

  • DECIMALを使った計算式のオーバーフロー

    (A * 100 /((B / C) * D) -0.05) という式を作っています。 型は以下の通りになります。 A の型:DECIMAL(18,7) B の型:DECIMAL(15,0) C の型:DECIMAL(5,0) D の型:DECIMAL(3,0) 結果を小数点第1まで表示したいけど、このままだとB がDECIMAL(15,0)の為小数点以下が出ないので、 とりあえずBをAと同じ型CAST(B as decimal(18,7))とうい風にキャストして小数点以下を出しています。 (A * 100 /((CAST(B as decimal(18,7))/ p_kadou_m) * p_kadou_to) -0.05) 今はうまく動作しているのですが、オーバーフローが出ないか心配しています。 オーバーフローを発生させないようにするにはどこを配慮したら良いのでしょうか。 CASTしているBの桁は今、桁は(18,7)にしているのですが、何が最適になるのでしょうか。

  • Double型について

     ずっと疑問でした、教えて下さい。 ついにその疑問を解き明かさなければ 次に行けない事になりました。 型はDoubleで計算をすると 0.7015-0.7=1.50000000000006E-03 という結果になりますが、 最後の6ってなんですか?この結果で比較をすると、 たまにはじかれる処理が出てくるのです。 ホントは0.0015でしょ? 他に良い方法があれば合わせて どうぞ宜しくお願いします。

  • C言語でintをdoubleに

    C言語でプログラミングを書いています。 10問の問題の正解数に応じて正答率を出すプログラムを書いているのですが、正解数を数えるものをintで定義(seikaiとする)し、正答率の計算結果を出すものをdoubleで定義(rituとする)しました。 seikaiをインクリメントで数え ritu=seikai/10*100 という計算をしました。このrituを%fで表示させようとしても正しく表示されません。intで定義したものを計算に用いて、その計算結果をdoubleで定義したもので表示することはできないのですか?? また、自分で調べたら、ritu=(double)seikai/10*100とやるというものがありましたが、”(double)”を使わずに計算を反映させることはできませんか?

  • double型の減算がうまくいかない

    Java初心者です。 今、Javaの勉強中で、double型の計算を行っています。 double型同士の減算を行った結果、思っていた結果と違う値が帰ってきたので、原因、もしくは解決方法をお教え頂ければと思います。 ソースは以下 public static void main(String[] args) { //値A double longitudeA = -73.98289; //値B double longitudeB = -73.98315; BigDecimal aDecimal = new BigDecimal(String.valueOf(longitudeA)); BigDecimal bDecimal = new BigDecimal(String.valueOf(longitudeB)); //減算 BigDecimal decimal = aDecimal.subtract(bDecimal); //小数点以下第5位で四捨五入し、出力 System.out.print(decimal.setScale(5, RoundingMode.HALF_UP).doubleValue()); } 出力される値として、 0.00026 を想定していたのですが、実際に出力されたのは 2.6E-4 でした。 BigDecimalのオブジェクトをそのまま出力すると想定通りの結果が出力されます。 一回Stringに型変換を行った後、Double#parseDoubleを行ったりしてみたのですが、 どうも思った通りの出力がされません。 解決策をお教え頂ければと思います。 よろしくお願いします。

専門家に質問してみよう