3

AS3コード:

import flash.utils.Dictionary;
var num1:Number = Number.NaN;
var num2:Number = Math.sqrt(-1);
var dic:Dictionary = new Dictionary( true );
trace(num1); //NaN
trace(num2); //NaN
dic[num1] = "A";
trace( num1 == num2 ); //false
trace( num1 === num2 ); //false
trace( dic[num1] ); //A
trace( dic[num2] ); //A

キー比較メソッドについて... "Dictionaryクラスを使用すると、プロパティの動的コレクションを作成できます。これにより、キー比較に厳密な等式(===)が使用されます。オブジェクトがキーとして使用される場合、オブジェクトのIDが検索に使用されます。オブジェクトをアップしますが、オブジェクトでtoString()を呼び出して返される値ではありません。」

ドキュメントに記載されているように、Dictionaryが厳密な等式を使用している場合、num1 === num2がfalseであるにもかかわらず、dic[num1]がdic[num2]と同じハッシュスロットに解決されるのはどうしてですか。

4

2 に答える 2

2

アドビが提供する説明は、正直に言うと正確でも正確でもありませんが、より単純で、ほとんどの場合をカバーしています。

次のことを試してください。

for (var key:* in dic) trace(getQualifiedClassName(key));//will give you 'String'

Arrayこの動作はとにも当てはまりObjectます。

経験則として:と他のキーは文字列表現に変換されます (boolean 値と float 値、および をint含む) 。 intnullundefined

このDictionaryクラスは、非プリミティブ オブジェクトを に変換せず、String直接キーとして使用するという点で異なります。他のすべての値を処理する方法はObject、必要に応じて「継承」されます。

基本的に、Objectは文字列用と整数キー用の 2 つのハッシュで構成されます。そしてDictionary、おそらく単にオブジェクトのメモリアドレスを整数キーとして使用して、別のハッシュを追加します。

編集:実際の質問に対する実際の回答ではありませんが、Triynko のコメントに応じて、詳細に説明したい点です:

ハッキー?つまり、機能するように設計されていない方法で機能させるということですか? ええと... 64 ビット整数を処理するように設計されていないため、もちろんハックです。しかし、64 ビットは 64 ビットであり、整数または浮動小数点として解釈されます。

64 ビット整数を表すために 64 ビット浮動小数点数を使用することは、意味的に完全に間違っているため、すでに悪い考えです (通常、この種の誤用から問題が発生することが予想されます)。

しかし、文字列表現をキーとして使用することは (float をキーとして使用すると暗黙のうちに発生します)、単純な自殺行為です。

var f1:Number = 1000000000000003000000000.0;
var f2:Number = 1000000000000002000000000.0;
trace(f1 == f2);//false
trace(String(f1) == String(f2));//true ... kabooooom

前提条件は、float として解釈される値の文字列表現が等しい必要があるため、2 つの 64 ビット int がいつ衝突するかを判断するのは困難です。また、異なるプレーヤー バージョンでは、フロートの文字列変換が異なる場合があり、LightSparkなどの代替ランタイムも同様です。私は本当にこれに頼りたくありません。これにより、衝突を引き起こすのに十分なデータがある場合に、どこからともなく出てくるようなバグが発生します。そして、それらを追跡することを楽しむことはできません.

また、浮動キーは、ハッシュ検索に使用する前に文字列に変換する必要があるため、パフォーマンスが低下します。サイズが本当に気になる場合は、データを 64 ビット int として送信し、フラッシュ側でのみ 16 進文字列に変換する必要があります。とはいえ、多くの
人が XML や JSON の使用に非常に満足し ていることは指摘しておきますが、XML や JSON ははるかにオーバーヘッドが大きくなります。

帯域幅とその他のハードウェア リソースは安価です。開発には費用がかかります。メンテナンスが容易で堅牢なアプリを作成する必要があります。そうしないと、長期的にはコストが高くなります。


グリッツback2dos

于 2010-05-25T18:35:00.993 に答える
-1

ここでかなりトリッキーなことにつまずいてしまったのではないでしょうか。Dictionaryキーにオブジェクト ID を使用し、オブジェクトを値でテストしないという意味で、宣伝どおりに機能します。ほとんどの場合、同じオブジェクトへの 2 つの参照は互いに厳密に等しいため、ほとんどの場合、厳密な等価性を使用した場合と同じ結果になります。

問題は、AS3 仕様に特殊なケースがあることです。NaN とのすべての比較は、定義により false と見なされます。NaN とそれ自体の比較も (サンプル コードが行っていることです)。比較で NaN が明示的に表示される場合、この効果に対するコンパイル時の警告さえあります。また、'true' や 'undefined' などの他のプリミティブの特殊なケースもあります。

別のテスト値を試すと、何が起こっているかを簡単に確認できるはずです。

import flash.utils.Dictionary;
var num1:Number = Number.POSITIVE_INFINITY;
var num2:Number = 1 / 0;
var dic:Dictionary = new Dictionary( true );
trace(num1); // Infinity
trace(num2); // Infinity
dic[num1] = "A";
trace( num1 == num2 ); // true!!
trace( num1 === num2 ); // true!!
trace( dic[num1] ); //A
trace( dic[num2] ); //A

慣れ親しんでいる言語によっては奇妙に思えるかもしれませんが、無限への 2 つの異なる参照を作成すると、AS3 は値が無限である 2 つの異なるオブジェクトを提供するのではなく、同じ無限物体。したがって、参照は厳密に等しく、同じ値をキーとします。Infinity の代わりに NaN を使用すると、値をそれ自体と比較する部分 (NaN が特殊なケースであるために false を返す場合) を除いて、あらゆる点で同じように機能します。

于 2010-05-26T17:28:59.463 に答える