有趣的 AS3 哈希情况。它真的像文档所说的那样使用严格平等吗?

发布于 2024-09-03 02:42:37 字数 706 浏览 1 评论 0原文

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 为何为 false,而 dic[num1] 却解析为与 dic[num2] 相同的哈希槽

AS3 Code:

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

Concerning the key comparison method...
"The Dictionary class lets you create a dynamic collection of properties, which uses strict equality (===) for key comparison. When an object is used as a key, the object's identity is used to look up the object, and not the value returned from calling toString() on it."

If Dictionary uses strict equality, as the documentation states, then how is it that num1 === num2 is false, and yet dic[num1] resolves to the same hash slot as dic[num2]?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清风夜微凉 2024-09-10 02:42:37

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

您应该尝试以下操作:

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

此行为对于 ArrayObject 也适用。

根据经验:int 保持 int,任何其他键都会转换为其字符串表示形式(包括布尔值和浮点值,以及 null 和未定义)。

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

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

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

哈基?你的意思是,让它在一个
它不是设计来工作的吗?出色地...
因为它不是设计来处理
64位整数,当然是
黑客。但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,但它们的开销要严重得多。

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

问候
后退2dos

The description given by Adobe is neither exact nor correct to be honest, but it is simpler and covers most cases.

You should try the following:

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

this behaviour is true for Array and Object as well.

As a rule of thumb: int stays int and any other key is converted to its string representation (including boolean and float values, as well as null and undefined).

The Dictionary class is different in that it does not convert non-primitive objects to String, but uses them as a key directly. They way of handling all other values is "inherited" Object if you will.

Basically, an Object consists of 2 hashes, one for string and one for integer keys. And the Dictionary adds another hash, probably simply using the objects memory address as integer key.

edit: Not really an answer to the actual question, but a point I want to explain in detail, in response to Triynko's comment:

Hacky? You mean, making it work in a
way it's not designed to work? Well...
since it's not designed to handle
64-bit integers, of course it's a
hack. But 64-bits is 64-bits, whether
they're interpretted as an integer or
floating point.

Using 64 Bit floats to represent 64 Bit ints is already a bad idea, because semantically, it's completely wrong (you can usually expect problems to arise from this kind of misuse).

But then using their String representation as key (which implicetely happens if you use a float as key) is plain suicide:

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

You will have a hard time determining, when 2 64 bit ints will collide, since the prequisite is that the string representation of their values interpreted as floats must be equal. Also, different player versions might have different string conversion of floats, as may alternative runtimes such as LightSpark. I really wouldn't wanna rely on this. This yields the kind of bugs that seem to come out of nowhere, when there's enough data to cause collision. And you will not enjoy tracking them down.

Also, float keys perform worse, since they have to be converted to strings before used for hash look up. If you are really so concerned about size, then you'll have to transmit the data as 64 bit int and convert it to a hex String on flash side only.
None the less, I would point out, that many people are extremely happy using XML or JSON, which has far worse overheads.

Bandwidth and any other hardware resources are cheap. Developement is expensive. You should write your apps to be maintainable and robust, otherwise they cost you more in the long run.

greetz
back2dos

双马尾 2024-09-10 02:42:37

恐怕你在这里被一些非常棘手的事情绊倒了。 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 在各个方面的工作方式都是相同的,除了将值与其自身进行比较的部分 - 当由于 NaN 是一种特殊情况而返回 false 时。

I'm afraid you've tripped over something pretty tricky here. Dictionary works as advertised in the sense that it uses object identities for keys, and does not test objects by value. And in most cases, that works out to the same thing as using strict equality, because in most cases two references to the same object are strictly equal to each other.

The wrinkle is that the AS3 specification has a special case: all comparisons with NaN are considered false by definition - even comparisons between NaN and itself (which is what your sample code is doing). There is even a compile-time warning to the this effect if NaN appears explicitly in the comparison. Also, there are other special cases for some other primitives like 'true' and 'undefined'.

It should be easy to see what's going on if you try a different test value:

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

That might seem odd depending on what languages you're used to, but all it means is that when you create two different references to infinity, AS3 doesn't give you two different objects whose value is infinity, it gives you two references to the same infinity object. Hence the references are strictly equal and they key to the same value. And using NaN instead of Infinity works the same way in every respect, except the part where you compare the value to itself - when it returns false due to NaN being a special case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文