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

投稿日: 2005/05/22(Sun) 03:56
投稿者Starfish
Eメール
URL
タイトルRe: バグかどうかはさておき

> VBのバグ、と断定してしまうのも如何なものでしょう。
> (本文部では、「と思います」とあるのに、タイトルでは「バグです」と断定していますよね)
>
> もしもそれが(仕様ではなく)障害だと認定されるとしても、その原因が
> 本当にVB側にあるのか、それとも他の理由なのか(たとえば、OLEに問題があるとか)と
> いった情報は、Microsoft側できちんと検証してから決定される事であり、
> 我々が軽々しく決め付けるべきでは無いかと思っています。

 これは、VBのバグだと思っています。マイクロソフトが障害だと認定するかどうかは
関係ないです。自分が、バグだと思えばバグだと言います。


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

 この情報は、VB4.0の情報ですから。以下の結果も32になりますし。
確か、VB4.0のころは10進型はなかったと記憶しています。VB6.0では、
これはそのまま当てはまらないと思います。

Dim a As Currency, b As Currency
a = 32
b = 1000
a = Fix((a / b) * 1000)

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

 VB6.0では、通貨型同士の除算は、結果は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)と同等の意味を持ちます。

 わたしは、Int(0.0282 * 10000)が必ず281を返すのなら、それは問題ないと思っています。
今回は、281と282を返す場合があり、それがバグだといっているのです。状況から判断して
282を返すつもりが281を返す様に見えます。
 Int さんの質問のInt(0.0282 * 10000)とa = 0.0282 * 10000=> Int(a) の結果の
違いの原因が何かというと、誤差が原因ではなく、このバグにより発生しているというのが
私の認識です。


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

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

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