C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: -1,#IND 、 1,#INF の判定


(過去ログ 133 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■78659 / inTopicNo.1)  -1,#IND 、 1,#INF の判定
  
□投稿者/ Massy (1回)-(2016/02/03(Wed) 11:52:23)

分類:[.NET 全般] 

お世話になっております。
今回もよろしくお願い致します。

「VB6」で作成されたプログラムを「VB2010」に変換しています。
とりあえず時間が優先なので、VB6臭さの漂うプログラムのまま移行しています。

移行はほぼ終わり、計算結果を確認しているところですが、次のような違いがありました。

A = 0 / 0
B = 1 / 0

◆VB6
Dim A as Variant
Dim B as Variant

A = 0
B = 0


◆VB2010
Dim A as Object
Dim B as Object

A = -1,#IND{Single}
B = 1,#INF{Single}

0割しないように、計算するまえにチェックすればいいというのは分かっていますが、計算式が非常に多いのと時間が優先のため、もし -1,#IND、1,#INF の時には、0 を設定したいのです。

A、BがObjectなのは、とりあえず値を格納するためのバッファのためです。(Ingeterの時も、String の時もあります。)
以下、質問です。

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Q1.
If (-1,#IND の時) or (1,#INF の時) の条件式はどのように記述するのでしょうか?

ちなみに、

IF ((1 / 0) = A) or ((0 / 0) = A) then では、引っかかりませんでした。((1 / 0)の結果が、Singleでないから?)


−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Q2.
Q1のIF文以外に、計算結果として追加すべき判定項目はありますか?


以上、よろしくお願い致します。
引用返信 編集キー/
■78660 / inTopicNo.2)  Re[1]: -1,#IND 、 1,#INF の判定
□投稿者/ Massy (2回)-(2016/02/03(Wed) 11:54:02)
補足

.net VB 2010 を使用しています。
引用返信 編集キー/
■78662 / inTopicNo.3)  Re[2]: -1,#IND 、 1,#INF の判定
□投稿者/ shu (800回)-(2016/02/03(Wed) 12:22:02)
2016/02/03(Wed) 13:21:05 編集(投稿者)

No78660 (Massy さん) に返信

> もし -1,#IND、1,#INF の時には、0 を設定したいのです。
それをしてしまうと
後の計算に影響は出ないのでしょうか?
0 / 0 は1に近いし
1 / 0 は限りなく大きい数(∞)に
なるので0にするのはかなり不適切です。

一応
1,#INF => Double.IsInfinity(1/0) の結果がTrueになります。
-1,#IND => Double.IsNaN(0/0)の結果がTrueになります。
Singleでも同様。


引用返信 編集キー/
■78665 / inTopicNo.4)  Re[1]: -1,#IND 、 1,#INF の判定
□投稿者/ 魔界の仮面弁士 (638回)-(2016/02/03(Wed) 12:48:23)
2016/02/03(Wed) 13:00:44 編集(投稿者)

No78659 (Massy さん) に返信
> とりあえず時間が優先なので、VB6臭さの漂うプログラムのまま移行しています。
お疲れ様です…


> A = 0 / 0
> B = 1 / 0
ちなみに「/」演算の結果は、基本的には Double になります。
これは VB6 でも .NET でも一緒。

一方、「Mod」演算子の動作は、VB6 とは違うので注意してください。
たとえば、「10.1 Mod 1.5」の演算結果は、
VB6 では「Long の 0」ですが、
VB.NET では「Double の 1.0999999999999996」です。



> ◆VB6
非数値や無限大は浮動小数点型の値の一種であり、
実は VB6 の Single/Double/Variant でも保持できます。
言語レベルでのサポートは無いので、あまりお目にかかることは無いですが。


> 0割しないように、計算するまえにチェックすればいいというのは分かっていますが、
VB6 同様、0 除算をエラーにしたいのであれば、Double や Single ではなく、
Decimal 等に置き換えることも検討してみてください。
精度や範囲が異なるので、単純には行かないかも知れませんけれども。


あるいは、四則演算をサポートした独自の数値側を設ける方法や、
0 除算を行う拡張メソッドを作成するといった手もあります。

Module Module1
 <System.Runtime.CompilerServices.Extension()>
 Public Function Div(ByVal this As Double, ByVal value As Double) As Double?
  Return If(value = 0.0, DirectCast(Nothing, Double?), this / value)
 End Function
End Module

 Dim a As Object = 123.45 / 0.0   '+∞
 Dim b As Object = 123.45.Div(0.0) 'Nothing

上記は、VB6 でいうところの Empty を連想して、Nothing を返しましたが、
例外にしてしまったり、0 扱いにしてしまったりといったこともできます。


> 計算式が非常に多いのと時間が優先のため、もし -1,#IND、1,#INF の時には、0 を設定したいのです。
計算後に判定するなら、
 Double.IsNaN
 Double.IsInfinity
 Double.IsNegativeInfinity
 Double.IsPositiveInfinity
といったメソッドが用意されています。


> IF ((1 / 0) = A) or ((0 / 0) = A) then では、引っかかりませんでした。
(今回の移行後で良いので、Or ではなく OrElse に置き換えることを検討しましょう)


> ((1 / 0)の結果が、Singleでないから?)
問題は 0 / 0 の方です。

1 / 0 = +∞
-1 / 0 = -∞
0 / 0 = 非数値


無限大については、大小関係が明確なのですが、
非数値(NaN) はデータベースの Null と同様に「不定な値」であるため、
四則演算の結果は常に NaN のままですし、比較しても False となります。
引用返信 編集キー/
■78670 / inTopicNo.5)  Re[3]: -1,#IND 、 1,#INF の判定
□投稿者/ Massy (3回)-(2016/02/04(Thu) 10:43:30)
shuさん、魔界の仮面弁士さん

懇切丁寧なご説明ありがとうございます。
とりあえず、時間を優先した.net VB 2010 への変換プログラムは動くようになりました。

あとは、少し時間を掛けて、VB6臭さを消していく作業を行います。
0割等、大変ためになりました。


あと1点、私が勘違いしておりました。
VB6でも、(1 / 0)、(0 / 0)はオーバーフローしていました。オーバーフロー(エラー)の際は0を設定するのIF文を見落としておりました。

(1 / 0)、(0 / 0)は、0でないことは承知致しておりますが、この計算では「0」は異常値を示すので前任者はあえて、注意を促すために0を設定したと思われます。


本当にありがとうございます。
またよろしくお願い致します。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -