タイトル : Re^4: 数字の比較について 投稿日 : 2017/01/19(Thu) 22:00 投稿者 : 魔界の仮面弁士
> ただ k = 2.3 でビルドエラーにならないのが不思議ではあります 値としては範囲内なので、エラーにはなりません。 同様の理由で、 'UInt64 の値を Int32 に代入 Dim i As Integer = 123UL なども OK です。 ただし、これは「定数値」や「リテラル」に限られます。 変数やプロパティ値だった場合、たとえば Dim a As UInteger = 123UL Dim b As Integer = a あるいは Dim x As Double = Double.MaxValue Dim y As Single = x などだと、Option Strict On で弾かれます。 ということで、実は ' MaxValue はプロパティではなく「定数」 Dim x As Single = Double.MaxValue も、Option Strict に関わらずコンパイル可能です。 それどころか、VB6 と違って実行時例外(オーバーフローエラー)にさえなりません。 > =を問題にするならdecimal型でなければならないという事になりますか? なりません。そもそも Decimal は、有効桁数は広いものの、扱える範囲は狭いですし。 (たとえば CDec(Single.Epsilon) は、Decimal.Zero に丸められてしまいます) 今回の件について言えば、Single 型で統一していれば問題は出なかったはずです。 型変換を伴うのであれば、たとえ Decimal を併用したとしても、 No11786, 11787 で述べたような、縮小変換/拡大変換による差異は生じ得ます。 すべての小数を Decimal で統一するにしても、たとえば「^ 演算子」ですとか、 「PointF 型」「Math.Pow メソッド」などなど、Decimal が使えないケースは存在します。 重要なのは、データ型を意識して使い分けると言うことですね。 良い機会ですし、曖昧なままにせず、それぞれの型の特性を正しく理解しておくことをお奨めします。 > vb6.0でSingle型で定義したのはvb2005では少なくともDouble型に > しないとうまく動かないという結論となりました 折角なので、VB6 側の動作についても説明しておきましょうか。 ――まずはリテラル表記について: ご存知かも知れませんが、VB6 では、2.3R や 2.3F といった数値リテラルは使えません。 しかし、型文字(Type Characters)を使うことで区別して記載できます。 VB6 の「2.3」や「2.3#」は Double 型ですし、 VB6 の Single 型リテラルは「2.3!」です。 もちろん「2.3E0」などの指数表現も使えます(VB6 でも VB.NET でも)。 ただし「2.3D0」形式は、VB.NET ではサポートされなくなっています。 (VB.NET で使うと、コンパイルエラー BC30827 が発生します) ということで、最初の質問にあった Dim K As Single に対する 比較処理についても、 No11786 に書いたのと同じ理由により、 本来は VB6 と言えども If K = 2.3! Then のように書くべきでしょう。 ――次に、浮動小数点数の扱いについて: 浮動小数点型(Single / Double)の精度は、VB6 と VB.NET とで違いはありません。 非数値がサポートされるようになったり、文字列表現が多少変更されたりといった差異はありますが。 では、どうして VB6 と VB.NET とで If K = 2.3 Then の結果が異なっていたのかと言えば、VB6 では If CDbl(K) = 2.3R Then 'これは False の判定ではなく、 If K = CSng(2.3R) Then 'これは True の方の比較処理が行われていたためです。 VB6 ヘルプ『比較演算子』の項より引用: > 単精度浮動小数点数型 (Single) の値を倍精度浮動小数点数型 (Double) の値と比較すると、 > 倍精度浮動小数点数点型の値は単精度浮動小数点数型の値の精度に丸められます。 上記には、通貨型(Currency) や通貨型(Decimal) についても述べられていますので、 併せてチェックしてみてください。VB6 の Decimal 型は、あまり馴染みが無いかもしれませんが。 こうした仕様変更は他にもあります。たとえば answer = 10.25 Mod 3.5 が、VB6 だと Long 演算で「2」になるのに対し、 VB.NET だと Double のまま「3.25」が返されるとか、 answer = 1.0 / 0.0 が、VB6 だと 0 除算エラーになるの対し、 VB.NET だとエラーにならず、+∞ になるとか…。 |