投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/9/5 13:16:23
> 下から3行目のCDbl(TextBox1.Text)部分にエラーが出てしまいます。

まず1点目。
CDbl ではなく、Double.TryParse や Decimal.TryParse を使いましょう。

TryParse メソッドは、「数値に変換できなかった場合」はエラーになるのではなく、
変数に数値をセットすると同時に、変換の成否を True / False で返しつ、
かつ、変換できなかった時には変数の値をゼロにするというものです。


TryParse メソッドは、ここのサイトだと投稿プログラム[BMI測定]の解説などで使われています。
http://rucio.o.oo7.jp/main/Toukou/T9_BMI.htm

初級講座だと、第16回の 2-13 あたり。
http://rucio.o.oo7.jp/main/dotnet/shokyu/standard16.htm



2点目。

Double 型よりも Decimal 型の方がおすすめです。
TextBox1.Text だと文字列型になるため、数値型への変換が必要ですが、
NumericUpDown1.Value からであれば、最初から数値型である Decimal として結果が得られます。

また、NumericUpDown コントロールならば不正な数値が入力される心配もありません。
NumericUpDown には、入力可能な最小値/最大値を設定するプロパティや、
小数点以下の桁数を指定するためのプロパティや、三桁区切りのカンマの有無なども設定できます。


3点目。

上記で Decimal を推す理由ですが、
これは Double が誤差を含みやすいデータ型だからです。

これは、Double の内部表現が 2進小数であることに由来しています。
電卓で使うのは通常、 10進数表記であるはず。

たとえば 2進小数 は、1÷10 などを正確には表現できません。
½、¼、¾、⅝ といった値であれば誤差なく保持できますが…。

Dim a As Double = CDbl("0.1")
Dim b As Decimal = CDec("0.1")

'0.1 を 10 回足す 
Dim x As Double = a + a + a + a + a + a + a + a + a + a
Dim y As Double = b + b + b + b + b + b + b + b + b + b

If x = 1.0R Then   '1.0R や 1.0# は、「Double 型の 1.0」を意味する表記です。 
    MsgBox("a を 10 回足すとは 1.0 です")
ElseIf x < 1.0R Then
    MsgBox("a を 10 回足した値は 1.0 未満です")    ' ここに入る 
Else
    MsgBox("a を 10 回足した値は 1.0 より大きいです")
End If

If y = 1.0D Then   '1.0D や 1.0@ は、「Decimal 型の 1.0」を意味する表記です。 
    MsgBox("b を 10 回足すとは 1.0 です")   ' ここに入る 
ElseIf y < 1.0R Then
    MsgBox("b を 10 回足した値は 1.0 未満です")
Else
    MsgBox("b を 10 回足した値は 1.0 より大きいです")
End If



たとえば 1÷3 という計算結果を小数として保持する場合、
3 進小数であれば、小数点以下 1 桁あれば割り切れますが、
10進小数だと0.333333…という循環小数になるため、
有限の桁で表そうとすると誤差が生じてしまい、
本来の値よりも少し小さい値になります。


それと同様、1÷10 という計算結果を小数として保持する場合、
10 進小数ならば割り切れますが、
2 進小数の場合、有限の桁で表そうとすると誤差が生じることになります。
それが、上記のサンプルで 10 回足しても 1.0 に戻らなかった理由です。


というわけで、内部的に 2 進数で管理される Double 型の代わりに、
10進数管理の Decimal 型をお奨めします。
扱える値の範囲が Double よりは狭くなりますが、一般的な電卓なら十分かと。