現在、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で質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 【前回の続き続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/24 20:49
- Visual Basic(VBA) 【ご教示ください】VBAの記述方法がわかりません。 2 2022/08/12 21:28
- Visual Basic(VBA) VBAが止まります。 3 2022/08/31 14:09
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- Visual Basic(VBA) VBAでoutlook365が起動しません。 4 2022/08/25 13:31
- Visual Basic(VBA) 【前回の続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/16 16:44
- Visual Basic(VBA) エクセルのマクロについて教えてください。 2 2023/07/15 15:48
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Visual Basic(VBA) ExcelVBAに関する質問 3 2023/02/17 10:47
- Visual Basic(VBA) VBA★PDFをPDFアプリで印刷しようと思っていますが上手くゆきません 1 2022/06/06 22:04
このQ&Aを見た人はこんなQ&Aも見ています
-
性格の違いは生まれた順番で決まる?長男長女・中間子・末っ子・一人っ子の性格の傾向
同じ環境で生まれ育っても、生まれ順で性格は違うものなのだろうか。家庭教育研究家の田宮由美さんに教えてもらった。
-
VB6.0-整数と余りを求める
Visual Basic(VBA)
-
実数の整数部,小数部の取得
Visual Basic(VBA)
-
【VB6.0】 あるフォームから他のフォームへ値を受け渡したい
Visual Basic(VBA)
-
-
4
VB初心者。小数点以下の表示でつまづいています(涙
Visual Basic(VBA)
-
5
VBの「As String * 128」とは?
Visual Basic(VBA)
-
6
テキストボックスの入力制限
Visual Basic(VBA)
-
7
VB6.0のIsNull関数に相当するもの
Visual Basic(VBA)
-
8
小数点を含む数値かどうか判断の判断方法
Visual Basic(VBA)
-
9
VB6でユーザー定義型がNothingかどうか調べるには?
Visual Basic(VBA)
-
10
【VB6】実行ファイルとした後、コード閲覧は不可能に近いか
Visual Basic(VBA)
-
11
vb6で異なるのプロジェクト間で、値を渡したい
Visual Basic(VBA)
-
12
MSDNのコレクションがありません。MSDNを再インストールしてください。
Visual Basic(VBA)
-
13
VB6.0のデザイン時 コントロールの移動 Vista
Visual Basic(VBA)
-
14
VB6のFIX関数での誤差について
Visual Basic(VBA)
-
15
VBの質問#if 0 then ってどう言う意味?
Excel(エクセル)
-
16
Form_Load と Form_Activate のタイミング
Visual Basic(VBA)
-
17
VB6 開発環境のエディタに行番号を表示
Visual Basic(VBA)
-
18
VBでグローバル変数を宣言するには
Visual Basic(VBA)
-
19
ORA-01013のエラーについて経験のある方お願いします。
Oracle
-
20
条件付きコンパイル: #IF 1 Then と #IF 0 Then
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
初心者です。 C++ついて
-
VB6.0での小数点の扱いについて
-
2進数の足し算(C言語)
-
”/”を使わずに割り算したいんで...
-
float.h のテスト結果がおかしい
-
O(n log n)について2
-
c言語 立方根
-
16進数 加算 減算 C言語
-
VB.net Double と...
-
c languageで 簡単な質問があ...
-
Log関数に関する質問
-
三角比の俯角の計算
-
ExcelでPC(パソコン)によって...
-
三菱シーケンサ(Aシリーズ)で...
-
BCD・HEX・BINについて
-
pythonの乗算の表示結果の差に...
-
有効数字について 以前質問をし...
-
10進数での「25」が2進数では「...
-
powf を使わずにべき乗を計算
-
色の判定
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
ExcelでPC(パソコン)によって...
-
ExcelのINT関数の計算結果がお...
-
16進数 加算 減算 C言語
-
VB.net Double と...
-
floatの有効桁数
-
三菱シーケンサ(Aシリーズ)で...
-
c languageで 簡単な質問があ...
-
除算を使わずに10で割りたい。
-
VBAでミリ秒まで出力する方法
-
VBAでの割り算の余りの求め方
-
VB6.0での小数点の扱いについて
-
VB6のFIX関数での誤差について
-
有効数字について 以前質問をし...
-
100桁の計算ができなくて困って...
-
浮動小数演算は実行環境の変化...
-
EXCELの関数"STDEV(標準偏差)"...
-
BCD・HEX・BINについて
-
コンピューターは指数関数をど...
-
乱数 なぜ剰余を使うのか
おすすめ情報