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 类允许您创建属性的动态集合,它使用严格相等 (===) 进行键比较。当使用对象作为键时,使用对象的标识来查找对象,而不是调用 toString() 返回的值。”

如果 Dictionary 使用严格相等,如文档所述,那么 num1 === num2 是如何为假的,而 dic[num1] 解析为与 dic[num2] 相同的哈希槽?

4

2 回答 2

2

Adobe给出的描述说实话既不准确也不正确,但它更简单,涵盖了大多数情况。

您应该尝试以下方法:

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

这种行为对于Array并且也是如此Object

根据经验:intstaysint和任何其他键都转换为其字符串表示形式(包括布尔值和浮点值,以及nulland undefined)。

该类Dictionary的不同之处在于它不会将非原始对象转换为String,而是直接将它们用作键。Object如果您愿意,他们处理所有其他值的方式是“继承的” 。

基本上,一个Object由 2 个散列组成,一个用于字符串,一个用于整数键。并且Dictionary添加了另一个哈希,可能只是使用对象内存地址作为整数键。

编辑:不是对实际问题的真正答案,而是我想详细解释的一点,以回应 Triynko 的评论:

哈基?你的意思是,让它以非设计的方式工作?嗯......因为它不是为处理 64 位整数而设计的,所以它当然是一个 hack。但是 64 位就是 64 位,无论它们被解释为整数还是浮点。

使用 64 位浮点数来表示 64 位整数已经是一个坏主意,因为从语义上讲,它是完全错误的(您通常可以预料到这种滥用会引起问题)。

但是然后使用他们的字符串表示作为键(如果你使用浮点数作为键,这会隐含地发生)是简单的自杀:

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

您将很难确定 2 个 64 位整数何时会发生冲突,因为先决条件是它们的值的字符串表示形式被解释为浮点数必须相等。此外,不同的播放器版本可能具有不同的浮点字符串转换,如LightSpark等替代运行时。我真的不想依赖这个。当有足够的数据导致碰撞时,这会产生似乎无处不在的错误。而且您不会喜欢追踪它们。

此外,浮点键的性能更差,因为它们必须在用于哈希查找之前转换为字符串。如果您真的非常关心大小,那么您必须将数据作为 64 位 int 传输,然后仅在闪存端将其转换为十六进制字符串。
尽管如此,我要指出的是,许多人都非常乐意使用 XML 或 JSON,它们的开销要低得多。

带宽和任何其他硬件资源都很便宜。开发成本高。您应该编写可维护和健壮的应用程序,否则从长远来看它们会花费您更多。

问候
back2dos

于 2010-05-25T18:35:00.993 回答
-1

恐怕你在这里被一些非常棘手的事情绊倒了。Dictionary就像宣传的那样,它使用对象身份作为键,而不是按值测试对象。在大多数情况下,这与使用严格相等的效果相同,因为在大多数情况下,对同一对象的两个引用彼此严格相等。

皱纹是 AS3 规范有一个特殊情况:根据定义,所有与 NaN 的比较都被认为是错误的 - 甚至 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

根据您使用的语言,这可能看起来很奇怪,但这意味着当您创建两个不同的无穷大引用时,AS3 不会给您两个不同的对象,其值为无穷大,它给您两个引用同一个无穷大对象。因此,引用是严格相等的,并且它们的关键值相同。并且使用 NaN 而不是 Infinity 在各个方面的工作方式都是相同的,除了将值与自身进行比较的部分 - 当它返回 false 由于 NaN 是一种特殊情况时。

于 2010-05-26T17:28:59.463 回答