VB6.0用掲示板の過去のログ(No.2)−VBレスキュー(花ちゃん)
[記事リスト] [新規投稿] [新着記事] [ワード検索] [管理用]

投稿日: 2005/05/21(Sat) 16:00
投稿者魔界の仮面弁士
Eメール
URL
タイトルバグかどうかはさておき

VBのバグ、と断定してしまうのも如何なものでしょう。
(本文部では、「と思います」とあるのに、タイトルでは「バグです」と断定していますよね)


もしもそれが(仕様ではなく)障害だと認定されるとしても、その原因が
本当にVB側にあるのか、それとも他の理由なのか(たとえば、OLEに問題があるとか)と
いった情報は、Microsoft側できちんと検証してから決定される事であり、
我々が軽々しく決め付けるべきでは無いかと思っています。

# 浮動小数点の誤差補正が、VB側で行われているのか、OS側で行われているのかは、
# 私も知りません。(^^; まぁ、知っててどうなる物でも無いですけれどね。


で、それはそれとして。


> 型変換する場合は
何故ここで、型変換、という言葉が出てきたのでしょうか。
そもそも、Int関数は型変換関数ではありませんよね(この関数は、データ型を変化させません)。


> ------------ 以下 サポート技術情報より抜粋 -------------
個人的には、この情報も正確なものとは言えない気がしています。

VBの[/ 演算子]においては、通貨型同士の除算は、倍精度浮動小数点型で演算されます。
確かに、演算誤差が発生した後、一時的に変数に格納する事で補正は行われるようですが、
根本的に除算時の誤差を減じたいのであれば、通貨型ではなく10進型を使うべきだと思うのです。
(10進型同士の除算であれば、10進型のままの精度で演算されますから)

そのため、サポート技術情報にある
》このような場合は、a / bの結果をいったん通貨型の一時変数に
》代入することにより、期待する結果を得ることができます。
という回避策については、個人的には不安を感じています。

結果を浮動小数点型で求めておいてから、その誤差を補正しようとするよりも、
そもそも浮動小数点が使われないような演算を使うようにした方が安全だと思うからです。


――という点を踏まえて。

まず、上記サポート技術情報で論じられている除算時の誤差に関しては、
これは VBの仕様というよりも、OLEの(VarDiv API等の)仕様かと思っています。

「10進型」の除算ならば、専用の VarDecDiv APIが用意されていますが、
それ以外の型(通貨型など)については、専用の除算APIが見当たりません。
おそらく、すべて VarDiv API にて処理され、結果が Double(またはSingle)の精度で
演算されるのでしょう。だとすれば、どうしてもこの時点で 2進数処理のための
誤差が発生してしまう可能性があるでしょう。


で。
ここで問題となるのは、話題に上がっているInt関数についてですが……

これも予想ですが、Double型に対するInt関数では、OLEの VarInt API が
使われているだと思います。VB6での動作は、このOLE APIの実装に
依存しているのでは無いでしょうか。

# とはいえ、VarInt において、浮動小数点の誤差がどのように処理されるのかは、やはり
# わかりません。(なので、バグか仕様かといった話には、ここでは触れないでおきます)

だからといって、Int関数の動作が全て問題になるのか、といえば、そうでも無い様な気がします。
10進型や通貨型に対して Int関数を発行した場合には、それぞれ、10進型専用の VarDecInt API、
通貨型専用の VarCyInt APIが用意されているからです。

10進型は内部的には10進数、通貨型は内部的には整数(固定小数点型)なので、もしも
これらの関数が使われるようにすれば、誤差が出る事は無いかと思うのです。

# なお、VB.NET の場合、Int(Double)/Int(Single)関数は、内部的には
# Math.Floor(Double)と全く同等の呼び出しが行われているようです。
# また、Int(Decimal)関数は、Decimal.Floor(Decimal)と同等の意味を持ちます。


- 関連一覧ツリー (★ をクリックするとツリー全体を一括表示します)

- 返信フォーム (この記事に返信する場合は下記フォームから投稿して下さい)

- VBレスキュー(花ちゃん) - - Web Forum -