
現在、VB6.0を使用しており、小数点の扱いに困っています。
Sub Keisan()
Dim A As String
Dim B As String
Dim C As String
A = 1.29033
B = 1.91458
C = CStr(A + CDec((B - A) / 6) * 3)
MsgBox C
End Sub
上記のプログラムを実行すると、
「1.602455000000001」と表示されますが、
電卓を用いて計算すると、
「1.602454998・・・」となり、微妙に誤差が出てしまいます。
小数点を整数にして計算→元の桁数に戻す、という
処理を行うと、誤差なく求めることが出来ましたが、
「もっとスマートなコードにして」と言われてしまいまして
どうしたものかと思っております。
この誤差を解決する方法は無いでしょうか?
No.3ベストアンサー
- 回答日時:
この問題は、パソコンと電卓との計算の誤差だと考えられます。
1.602455000000001と1.602454998 はとちらも結論から言うと正しいのだが。
問題は、(B-A)/6 が割りきれないところから出ていると思われます。
0.104041666666・・・・=(B-A)/6
電卓は、1演算の都度、小数点指定桁数で切り捨てて計算するみたいです。
これは、電卓の液晶画面が指定桁数しか表示出来ないところから来ている
と思われます。
今回の問題は、電卓に合わすとの事なので、合わす為には、演算が入る
度に、電卓と同じ桁数で切捨てればOKとの事になります。
ご質問のプログラムもそこを考慮して、CDec((B - A) / 6) とわざとCDec関数を
間に入れていますが、結局小数点9桁で切り捨てられていないので、切捨てられて
いない分だけ計算結果が大きくなります。
下記のプログラムが比較的簡単かなと思います。これでも完璧かどうか
わかりませんが、乗算・除算の計算の度に下のfint関数を呼び出す事です。
ここで注意するのは、fint関数の2番目の引き数です。この引数は、電卓の液晶画面の
表示桁数です。下のサンプルは、表示桁数10桁(小数点も含む)にしています。
Sub Sub Keisan()
Dim A As Double
Dim B As Double
Dim C As String
A = 1.29033
B = 1.91458
C = A + fint((B - A) / 6, 10) * 3
MsgBox C
End Sub
Function fint(cd as double, ck as integer) As Double
cm = Format(cd, "#.000000000000000000")
fint = Left$(cm, ck)
End Function
尚、演算の内容によっては、上のプログラムでもごくまれに電卓と誤差が
出る可能性があります。確立的にはどれだけかは分かりませんが0.01%
位の確立で誤差が発生するかもしれません。(推測です)。
100%絶対に合わすのであれば、ご指摘の通り、整数にて処理を
するのが確実です。ただ、プログラムが複雑になる分バグも出やすく、
簡潔でそこそこ精度があるのであれば、上のプログラムで充分だと
思います。
ありがとうございます!!!
教えて頂いた方法で上手くいきました!!!
電卓の表示桁数で抜き取ればよかったんですね。
言われてみると納得です。
プログラムのこういう瞬間「は」すごく楽しいと思いますw
しかし、小数点の演算箇所は相当数あるんですよね・・・
あれ全部修正してテストするのかと思うと怖くなってきましたw
No.4
- 回答日時:
まず、A, B, CがStringの定義なのがアレですね…
誤差を気にするのなら浮動小数点もダメです。
全てVariantで定義して、
A = CDec(1.29033)
とかにしましょう。
あと、計算の中間結果((B-A)/6 とか)も浮動小数点に勝手に変換されると
まずいので、
C = A + (B - A) / CDec(6) * CDec(3)
とかにしたほうがいいかも。
(検証はしてません、あしからず)
回答ありがとうございます。
計算結果は、
A + (B - A) / CDec(6) * CDec(3) = 1.602455
でした(この値でも正しいと思うんですけどねw)。
ちなみにString型で定義してある理由ですが、、、、、不明ですw
No.2
- 回答日時:
この演算結果は1.602455が正解なのでは?
CDec((B - A) / 6) * 3 は CDec((B-A)/2) とほぼ等価考えます
0.62425 / 2 = 0.312125
これに 1.29033 を加算するのですから 1.602455 となると思います
CDec((B - A) / 6) * 3部分に関して 有効桁数以下でRound関数で丸めてしまうといった手法も考えられます
C = CStr( A + Round( CDec( ( B - A )/ 6 ) * 3, 8 ) )
といった具合です
回答が遅くなり申しわけありません。
実は「3」はまた別の式を使って求めているので、正確には、
C = CStr(A + CDec((B - A) / 6) * (3))となります。
質問が正確でなくて本当にすいません。
なので、計算の順序を変えるというのは難しいかなと思っています。
回答頂きました式を実行すると、
CStr( A + Round( CDec( ( B - A )/ 6 ) * 3, 8 ) ) = 1.602455
となりました。
正確な式と、桁数を増やしてみましたが、
CStr(A + Round(CDec((B - A) / 6), 12) * (3)) = 1.602455000001
となり、まだ誤差が出てしまいました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
VB6.0-整数と余りを求める
Visual Basic(VBA)
-
VB6 開発環境のエディタに行番号を表示
Visual Basic(VBA)
-
VB6.0 のformat関数について
Visual Basic(VBA)
-
-
4
VB6のプロジェクトロードエラーについて
Visual Basic(VBA)
-
5
VB6で、長い時間かかる処理実行中の表示の工夫について
Visual Basic(VBA)
-
6
VB6 配列を初期化したい
Visual Basic(VBA)
-
7
MSDNのコレクションがありません。MSDNを再インストールしてください。
Visual Basic(VBA)
-
8
VBで実行中のEXEファイルの情報を取得したい
Visual Basic(VBA)
-
9
VB初心者。小数点以下の表示でつまづいています(涙
Visual Basic(VBA)
-
10
VBの「As String * 128」とは?
Visual Basic(VBA)
-
11
VB6.0 プロジェクトオープン時のエラーについて
Visual Basic(VBA)
-
12
VB.netでメソッドからコントロールを取得
Visual Basic(VBA)
-
13
visual basic初心者です。 visual studioで電卓を作成しています。 実行時にテ
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
有効数字について 以前質問をし...
-
10進数での「25」が2進数では「...
-
VB.net Double と...
-
float.h のテスト結果がおかしい
-
三菱シーケンサ(Aシリーズ)で...
-
2進数の0.2?
-
fortranで図形の面積を求めるに...
-
ExcelのINT関数の計算結果がお...
-
時刻の比較
-
O(n log n)について2
-
EXCELの関数"STDEV(標準偏差)"...
-
計算の丸め誤差の解消について
-
「Aに対するBの割合」と「Aに対...
-
Enterキーを押されたら次の処理...
-
Aの値からBの値を除するとは??
-
信頼区間の1.96や1.65ってどこ...
-
std::set<int> で、ある値が何...
-
20'(角度)の計算がわかりま...
-
数学で、定数aの値を求めよって...
-
do-while文が禁止される理由
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
有効数字について 以前質問をし...
-
c languageで 簡単な質問があ...
-
ExcelでPC(パソコン)によって...
-
O(n log n)について2
-
2進数の足し算(C言語)
-
16進数 加算 減算 C言語
-
EXCELの関数"STDEV(標準偏差)"...
-
三菱シーケンサ(Aシリーズ)で...
-
VB.net Double と...
-
MATLABでの行列の全要素の和
-
除算を使わずに10で割りたい。
-
floatの有効桁数
-
”/”を使わずに割り算したいんで...
-
ExcelのINT関数の計算結果がお...
-
VBAでミリ秒まで出力する方法
-
VB6.0での小数点の扱いについて
-
Fortran において変数の定義
-
計算の丸め誤差の解消について
-
C言語について質問です。
-
CRCの計算方法について
おすすめ情報