OKWAVEのAI「あい」が美容・健康の悩みに最適な回答をご提案!
-PR-
解決
済み

Double型について

  • すぐに回答を!
  • 質問No.216304
  • 閲覧数347
  • ありがとう数7
  • 気になる数0
  • 回答数8
  • コメント数0

お礼率 68% (77/113)

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

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

  • 回答No.8
レベル12

ベストアンサー率 40% (230/562)

またまた、話を付け加えますと、DecimalはVariant型の内部処理形式でしか使えません。

Dim X As Decimal '不可

Dim Y As Variant 'もちろんAs Variantは省略可
Y = CDec(0.10000000000000000000000001)
Debug.Print Y '0.1が出る
Y = CDec(0.1) + CDec(0.00000000000000000000000001)
Debug.Print Y '0.10000000000000000000000001が出る
Y = CDec("0.10000000000000000000000001")
Debug.Print Y '0.10000000000000000000000001が出る

演算はまず、Variant型の内部形式がDecimalであることを認識して、それから適切な演算関数が呼び出されるのと、内部表現が複雑なこともあって、As Currencyで直接宣言した通貨型よりも多少演算速度が遅れます。

また、リテラル値でとして0.10000000000000000000000001と書いた後CDecで変換しても、0.10000000000000000000000001はDouble型ですから、かってに0.1に丸められます。
それもCDecしても0.1のままです。
3つ目の文のように文字列は正確に変換してくれますが、2個目の文のように計算する必要はないものの、文字列という超低速の形式からの変換ですから、速度は最も下です。

割り算をするとDecimal型であっても演算結果がDoubleになってしまったりと障害は多いですが、精度の高さだけがウリです。
演算速度が遅いと言っても、1000回や10000万回の計算では気になるほどではありません。

VB6になって、始めてDecimalを見つけたときは、おもしろくていろいろ遊んでみました。
HUKAHIREさんも、いろいろな式を書いてみて、いろいろ試してみてください。
-PR-
-PR-

その他の回答 (全7件)

  • 回答No.2
レベル13

ベストアンサー率 26% (267/1014)

実数演算の宿命です。 ちなみに 「電卓は、10進扱いで、このような誤差はない」 とのたまう人が居ました。 「VBの甘い罠」/実数における誤差 (↓URL) ...続きを読む
実数演算の宿命です。

ちなみに
「電卓は、10進扱いで、このような誤差はない」
とのたまう人が居ました。

「VBの甘い罠」/実数における誤差
(↓URL)
補足コメント
HUKAHIRE

お礼率 68% (77/113)

 ご回答ありがとうございました。どうしようもないものなのですか、、?
投稿日時 - 2002-02-12 13:59:43
お礼コメント
HUKAHIRE

お礼率 68% (77/113)

 みなさん本当にありがとうございました。いろいろな方法で試してみましたがDecimalも不具合が出ないっぽいので採用かなと考えています。いろいろして頂いたのに私からなにもあげれませんが気持ちだけ、、(^-^)/■ チョコレートです。
投稿日時 - 2002-02-13 11:55:08


  • 回答No.1
レベル12

ベストアンサー率 40% (230/562)

これはdouble型が利用する記録方式として、 Windows系(x86系CPU) h × 16^n (16進数×16の自然数乗) Unixでよく使われるCPU b × 2^n (2進数×2の自然数乗) という方式を採っているからです。 人間は d × 10^n (10進数×10の自然数乗) という見かたをするので、表示するときは16進数や2進数を10進数に変換しなけれ ...続きを読む
これはdouble型が利用する記録方式として、

Windows系(x86系CPU)
h × 16^n (16進数×16の自然数乗)

Unixでよく使われるCPU
b × 2^n (2進数×2の自然数乗)

という方式を採っているからです。
人間は

d × 10^n (10進数×10の自然数乗)

という見かたをするので、表示するときは16進数や2進数を10進数に変換しなければなりません。
整数を変換するときは、問題ありません。
しかし、少数はほとんどの場合、10進数を16進数に変換したり、16進数を10進数に変換すると、どちらも無限小数となってしまいます。

たとえば、10進数で0.1という簡単な少数は、16進数では無限小数です。

無限小数を利用すれば、変換は互いに可逆です。
しかし、コンピュータには無限の記憶領域はないので、細かい部分は切り捨て(または繰り上げ)なければなりません。
それが今回の誤差です。

double型はおよそ10進数で15桁程度しか有効数字がありません。
0.7015と書いた場合、有効数字は15桁ですから、

0.7015 = 0.701500000000000

となります。
しかし、15桁目以降は不明です。
今回は保証されていない桁まで考えると

0.7015 = 0.701500000000000xx
-) 0.7 = 0.700000000000000yy
------------------------------
0.0015 = 0.00150000000000006

となってしまったのでしょう。
0.7015と0.7の最初の桁から15桁目まででは6という数字は現れませんでしたが、0.0015の最初の桁から15桁目まででは6が存在してしまうのです。
これを "桁落ち" といいます。

ある程度の科学計算では15桁もあれば十分です。
微妙な部分は切り捨てたり四捨五入します。

しかし、金額計算にdoubleを使ってはいけません。
利子などは数値をなん度もかけ算するので、誤差が無視できないところまでふくれあがります。
15桁などあっというまです。

VBでは金額計算に便利なCurrency型が用意されているので、金額計算をしているようならCurrencyを使います。
もちろん、少数5桁以下は切り捨てられます。
その代わり、精度は19桁ほどあります。
補足コメント
HUKAHIRE

お礼率 68% (77/113)

ご回答ありがとうございます。私の周りの人に「CDecすりゃいいよ」って冷たく言われるんですけど、、。それでは解決しない気がするんです、、私だけ、、?少数桁8桁ぐらいまで正確に計算する方法はないのですかね?
投稿日時 - 2002-02-12 13:48:47
  • 回答No.3
レベル12

ベストアンサー率 65% (276/422)

原因はもう述べられてますね。 >どうしようもないものなのですか、、? 1000倍した値をLong型に収めてから計算。 その値を1000で割ってはだめ?
原因はもう述べられてますね。

>どうしようもないものなのですか、、?
1000倍した値をLong型に収めてから計算。
その値を1000で割ってはだめ?
  • 回答No.4
レベル12

ベストアンサー率 65% (276/422)

ごめんなさい。きちんと読んでませんでした。 8桁なら1億倍ですね。 それ以前に >CDecすりゃいいよ ? (cdec(0.7015)- cdec(0.7000)) の出力値は確かに0.015でした。大丈夫なのでは? うーん 奥が深い。Cdec。。。考えもしなかった。。。 ...続きを読む
ごめんなさい。きちんと読んでませんでした。
8桁なら1億倍ですね。

それ以前に
>CDecすりゃいいよ
? (cdec(0.7015)- cdec(0.7000))
の出力値は確かに0.015でした。大丈夫なのでは?

うーん 奥が深い。Cdec。。。考えもしなかった。。。
補足コメント
HUKAHIRE

お礼率 68% (77/113)

 大丈夫ですかね?
投稿日時 - 2002-02-12 17:02:49
お礼コメント
HUKAHIRE

お礼率 68% (77/113)

 みなさん本当にありがとうございました。いろいろな方法で試してみましたがDecimalも不具合が出ないっぽいので採用かなと考えています。いろいろして頂いたのに私からなにもあげれませんが気持ちだけ、、(^-^)/■ チョコレートです。
投稿日時 - 2002-02-13 11:54:34
  • 回答No.6
レベル13

ベストアンサー率 34% (574/1662)

>Windows系(x86系CPU) >h × 16^n (16進数×16の自然数乗) 言語によるのかも知れませんが、Cを使っている場合は 2の指数形式、IEEEの形式ですね。 16の指数形式は、ミニコン関係で経験があります。 あと、自然数乗となってますが、正確には整数ですね。 負の値もありますから。 精度が必要で言語でそういう型が無い場合は TAGOSAKU7さん ...続きを読む
>Windows系(x86系CPU)
>h × 16^n (16進数×16の自然数乗)

言語によるのかも知れませんが、Cを使っている場合は
2の指数形式、IEEEの形式ですね。
16の指数形式は、ミニコン関係で経験があります。

あと、自然数乗となってますが、正確には整数ですね。
負の値もありますから。

精度が必要で言語でそういう型が無い場合は
TAGOSAKU7さんが言うような形で整数として扱います。

また、こういう誤差があるので、
こういう実数を扱うプログラムでは、=で判定せず、
差をとってある値より小さい場合は同じとみなすような
プログラムを書くのがよく使う手です.
お礼コメント
HUKAHIRE

お礼率 68% (77/113)

 みなさん本当にありがとうございました。いろいろな方法で試してみましたがDecimalも不具合が出ないっぽいので採用かなと考えています。いろいろして頂いたのに私からなにもあげれませんが気持ちだけ、、(^-^)/■ チョコレートです。
投稿日時 - 2002-02-13 11:54:04
  • 回答No.5
レベル12

ベストアンサー率 40% (230/562)

DecimalはVariant型の内部形式でしか使えませんが、0と0.0000000000000000000000000001~79,228,162,514,264,337,593,543,950,335の10進数を扱えるので、Currencyよりびっくりです。 もちろん、doubleのように指数を使って大きな数値を表すことはできませんが。 ...続きを読む
DecimalはVariant型の内部形式でしか使えませんが、0と0.0000000000000000000000000001~79,228,162,514,264,337,593,543,950,335の10進数を扱えるので、Currencyよりびっくりです。
もちろん、doubleのように指数を使って大きな数値を表すことはできませんが。
補足コメント
HUKAHIRE

お礼率 68% (77/113)

 じゃデシマル?は平気なんですよね?
投稿日時 - 2002-02-12 17:28:40
  • 回答No.7
レベル12

ベストアンサー率 40% (230/562)

>terra5: 16の指数形式は、ミニコン関係 ありゃ、すいません。 いい加減なことを言ってしまったようです。 整数でもいいですけど、DecimalもCurrencyも有効桁数だけならDoubleよりLongより上ですよ。 演算速度遅いですけどね。 もちろん、Longで計算して割り算するのとあんまり変わりません。 ...続きを読む
>terra5: 16の指数形式は、ミニコン関係
ありゃ、すいません。
いい加減なことを言ってしまったようです。
整数でもいいですけど、DecimalもCurrencyも有効桁数だけならDoubleよりLongより上ですよ。
演算速度遅いですけどね。
もちろん、Longで計算して割り算するのとあんまり変わりません。
お礼コメント
HUKAHIRE

お礼率 68% (77/113)

 みなさん本当にありがとうございました。いろいろな方法で試してみましたがDecimalも不具合が出ないっぽいので採用かなと考えています。いろいろして頂いたのに私からなにもあげれませんが気持ちだけ、、(^-^)/■ チョコレートです。
投稿日時 - 2002-02-13 11:53:18
このQ&Aで解決しましたか?
関連するQ&A
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


いま みんなが気になるQ&A

関連するQ&A

-PR-

ピックアップ

-PR-
ページ先頭へ