或者......你如何在没有得到整数结果的情况下进行异或?
我正在使用Actionscript 3.0并找到以下内容:
var a:Number = 3.000000004;
var b:Number = 29.999999999;
trace ("a: " + a); //3.000000004
trace ("b: " + b); //29.999999999
a ^= b;
b ^= a;
a ^= b;
trace ("a: " + a); //29
trace ("b: " + b); //3
显然,XOR操作正在将我的号码转换为整数。我对此感到有些惊讶,并不完全理解它背后的原因。但我知道其他按位操作也会将Number更改为int,所以我 感到惊讶。
尽管如此,有没有办法让XOR双打(又名数字)而不会被截断为整数?我最初使用上述XOR进行性能优化(这些数字开关在数组中执行了数百万次)。我假设如果我跳过临时变量,我会看到速度增加。唉,如果Number数据变为int,那么一切都是徒劳的。
只是想知道是否有解决方案,或者在这种情况下我是否需要放弃XOR。
(ps,我暂时无法检查此帖子,但在此期间欣赏任何建议,知识等)
(pps,如果你很好奇,这是我试图加速的方法,如果可能的话)
public static function reversePairs(values:Vector.<Number>):void {
//1, 2, 3, 4, 5, 6 -> 5, 6, 3, 4, 1, 2
var l:int = values.length;
var n:int = l * 0.5;
n -= n % 2;
for (var a:int = 0; a < n; a++) {
var b:int = (l - a) - 2 * ((a + 1) % 2);
//we cannot use xor because it truncates the decimal value
//values[a] ^= values[b];
//values[b] ^= values[a];
//values[a] ^= values[b];
//we MUST use a temporary variable instead
var c:Number = values[b];
values[b] = values[a];
values[a] = c;
}
}
答案 0 :(得分:4)
xor-swap操作不是优化。这是一种悲观情绪。
很难想到任何一个好主意的架构(每个架构四个步骤取决于前一个架构的完成,甚至假设读取 - 修改 - 写入内存到内存为原子......一个真正可怕的实现交换)。在内存中两个值之间进行交换的最佳方法通常是双读,然后是双写:
reg1 = mem1; reg2 = mem2;
mem1 = reg2; mem2 = reg1;
这些对中的每一对也可以并行执行(两个读取是独立的,并且两个写入也是独立的),因此操作可以分两步完成。 大多数优化编译器都能识别惯用的三步交换
{ type temp = x; x = y; y = t; }
生成两步调用代码,因为这是硬件的最佳方式。
通过使用原位减法-=
而不是inplace xor ^=
,可以获得浮点到“不良xor-swap代码”的“等效”。
然而,只有在准确性问题没有出现的情况下,这才是真正的交流。
答案 1 :(得分:1)
^=
是一个按位运算,而不是整数运算本身(参见,Adobe's docs)。想象没有像这样的东西是有帮助的。
实际上需要一些 more 临时变量来对一个带小数的数字进行异或,这不能解决速度问题。
虽然我无法提供重写交换的任何内容,但我建议你永远不要(永远!)在for循环中声明变量,除非你必须这样做。埃尔戈:
var b:int;
var c:Number;
for (var a:int = 0; a < n; a++) {
b = (l - a) - 2 * ((a + 1) & 1);
c = values[b];
values[b] = values[a];
values[a] = c;
}
另请注意,我使用1将模数更改为an additive mask,这应该更快。
除此之外,允许Vector类进行排序可能很有用,write a custom sort method可供您特定使用。