tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルVB2005での0除算例外について
記事No6661
投稿日: 2007/12/11(Tue) 15:35
投稿者たると
こんにちは、いつもお世話になっています。
以前はVB6.0を使用していたためDoubleでも0除算例外をキャッチ(スローというのでしょうか?)することができていたのですが、今回VB2005を使用するようになってから
Doubleで0除算例外がキャッチできなくなったことを知りました。
参考のサイト様より以下のソースでは例外がでませんでした。

Private Sub Button1_Click(...) Handles Button1.Click
    Dim a As Integer = 10
    Dim b As Integer = 0    
    Dim c As Double = 0    
    c = a / b
End Sub

このプログラムの場合aとbがint型のため4行目のソースコードを

c = CInt(a / b)

とすることで、例外をキャッチすることが可能なのですが、このa,bに小数点付きの値が
入る場合

Private Sub Button1_Click(...) Handles Button1.Click
    Dim a As Double = 11.111
    Dim b As Double = 2.222
    Dim c As Double = 0    
    c = CInt(a / b)
End Sub

としてしまうと、cに生じる0除算例外はキャッチすることができるのですが、
CIntでデータ型をinteger型にしてしまっているため、cには5が入ってしまいます。
正規処理ではcには小数点付きの数字が入るので、できればDoubleを使用し、例外の処理が
生じたときにキャッチしてやりたいのですが、どのような処理をすればよいのかがわからず困っています。
どなたかご教授お願い致します。

参考にしたURL
http://salv.miscnotes.com/2006/10/34_vb20050.php

[ツリー表示へ]
タイトルRe: VB2005での0除算例外について
記事No6662
投稿日: 2007/12/11(Tue) 16:49
投稿者魔界の仮面弁士
> Doubleで0除算例外がキャッチできなくなったことを知りました。
Double 型の場合、
 正数 ÷ ゼロ = +∞
 ゼロ ÷ ゼロ = 非数値(NaN)
 負数 ÷ ゼロ = -∞
となる仕様となっています。

これらの特殊な値については、Double型の共有メソッドで判定できます。
たとえば、正の無限大であるかどうかを判定するなら、
Double.IsPositiveInfinity メソッドですね。


ちなみに、これらの特殊な Double 値というのは、VB6 でも内部的には
利用可能でしたが、VB6 上では(0 除算等を行っても)生成できないため、
ヘルプ等には、特に記載されていなかったようです。

なお、VB6 で「無限大」や「NaN」データを構築する方法は、この辺りを参照。
蛇足までに。
http://hanatyan.sakura.ne.jp/vb60bbs/wforum.cgi?no=10740&reno=10733&oya=10731&mode=msgview&page=30


> c = CInt(a / b)
> とすることで、例外をキャッチすることが可能なのですが、
ただしそれは、ゼロ除算の例外ではありませんよね。


> このa,bに小数点付きの値が入る場合
それならば、「Decimal型」を利用してみては如何でしょうか?
求める演算精度にもよりますけれども。


> できればDoubleを使用し、例外の処理が
> 生じたときにキャッチしてやりたいのですが、
この場合に実装しておくべきことは、「例外処理」ではなく「If b = 0.0 Then」です。

今回の「DivideByZeroException」や「OverflowException」などといった例外は、
プログラム側で、事前に値を検証することで回避できるのですから、そもそも、
『それらの例外が発生しないようなプログラムを書く』のが、本来の姿だと思いますよ。

[ツリー表示へ]
タイトルRe^2: VB2005での0除算例外について
記事No6665
投稿日: 2007/12/11(Tue) 18:14
投稿者たると
魔界の仮面弁士さん、こんばんは。返信ありがとうございます。

> ちなみに、これらの特殊な Double 値というのは、VB6 でも内部的には
> 利用可能でしたが、VB6 上では(0 除算等を行っても)生成できないため、
> ヘルプ等には、特に記載されていなかったようです。
>
> なお、VB6 で「無限大」や「NaN」データを構築する方法は、この辺りを参照。
> 蛇足までに。
> http://hanatyan.sakura.ne.jp/vb60bbs/wforum.cgi?no=10740&reno=10733&oya=10731&mode=msgview&page=30
>
ありがとうございます。大変参考になります。
VB6.0では例外処理は
    Try
    'ソースコード
    Catch ex As Exception
        'エラー時の処理
    End Try

の形で済ましてしまうことが多く、あまり意識したことがなかったので大変参考になりました。

> > c = CInt(a / b)
> > とすることで、例外をキャッチすることが可能なのですが、
> ただしそれは、ゼロ除算の例外ではありませんよね。

除算を実行する前に、整数の数式は必ず Double 型に拡大変換されているので
オバーフローの例外になるのですね。
>
> > このa,bに小数点付きの値が入る場合
> それならば、「Decimal型」を利用してみては如何でしょうか?
> 求める演算精度にもよりますけれども。
>
データ型を「Decimal」に変換することで思い通りの処理ができるようになりました。
例外処理をキャッチすることばかりにとらわれていたのでデータ型を変更することを
思いつきませんでした(^^;
丁寧な返信ありがとうございました。

[ツリー表示へ]
タイトルRe^3: VB2005での0除算例外について
記事No6666
投稿日: 2007/12/11(Tue) 19:32
投稿者魔界の仮面弁士
> VB6.0では例外処理は
>     Try
>     'ソースコード
>     Catch ex As Exception
>         'エラー時の処理
>     End Try
> の形で済ましてしまうことが多く、
??? VB6 では、Try ステートメントはサポートされていないハズです。
On Error ステートメントならありますけれどね。

それと、Catch 句ですべての Exception を拾っていますが、むやみやたらと
Catch してしまうのはマズイです。処理すべき例外のみ拾うようにしましょう。
(拾った例外が想定外のものであったなら、Throw しなおした方が良いですよ)
http://www.ailight.jp/blog/kazuk/articles/6298.aspx


> 除算を実行する前に、整数の数式は必ず Double 型に拡大変換されているので
> オバーフローの例外になるのですね。
違います。
型が Double になったからではなく、結果が「無限大」だったからです。

Double に拡大変換された後の値が、Integer.MinValue 〜 Integer.MaxValue の
範囲内にあるならば、CInt してもオーバーフローにはなりません。


> データ型を「Decimal」に変換することで思い通りの処理ができるようになりました。
> 例外処理をキャッチすることばかりにとらわれていたのでデータ型を変更することを
> 思いつきませんでした(^^;
あれれ。たるとさんが参考にされていたサイト(猿頁)には、はっきりと
『ちなみに、Decimal型の場合は事前のDouble型変換が行われないので、0除算例外が発生します。』
という記述があったはずなのですが……。

[ツリー表示へ]