【问题标题】:Bitwise operation OR on (double) in Java not possible, possible in JavaScriptJava 中的按位运算 OR (double) 不可能,在 JavaScript 中可能
【发布时间】:2014-03-23 01:03:18
【问题描述】:

这是来自 Google Chrome Javascript 控制台的输出。

这里是 DrJava Java 控制台的输出。

我的 Javascript 代码是

(baseCPUCyclesPerIteration - CPUCyclesTotalRoundoff) | 0

如果两个变量都是整数但显然它们在 javascript 中是双精度的,则似乎在 Java 中编译得很好。虽然

typeof baseCPUCyclesPerIteration 透露 "number"

结果很明显它是一个双重数据类型。我不明白为什么按位 OR 0 在 Javascript 中适用于双精度,但不适用于 Java 双精度。

似乎| 0 的目的只是修剪双数据类型中的小数点。我猜在Java中相当于(int)(long)演员这是正确的吗?还是按位 | 0 做的不仅仅是修剪 javascript 中的小数点?

编辑: ya | 0 不只是在 javascript 中修剪只是运行了这个。 8899811111.111113453456754645 | 0 回来了 309876519.
(虽然我通过了双重限制,lol 仍然尝试在 javascript 中计算它,我猜这是发生溢出的地方)。

【问题讨论】:

  • 他们处理类型的方式不同(你的问题似乎是合理的,只是说:p,比较它们很混乱)
  • 因为在Java中,位运算符只能应用于原始整数类型...这是由语言定义的。
  • 在 Java 中是 | 0(int)(long) 相同吗?
  • 不知道,但最好使用parseInt()(在 JavaScript 中)恕我直言。否则,是的,您将使用 Java 进行强制转换以删除小数。请注意,您希望 long 处理所有 double,因为 double 中可能的整数值大于 int 支持的值
  • ya | 0 不只是在javascript中修剪只是运行了这个。 8899811111.111113453456754645 | 0 回来了 309876519(虽然我通过了双重限制,但我仍然尝试在 javascript 中计算它,我猜这是发生溢出的地方)。

标签: java javascript numbers double bitwise-or


【解决方案1】:

在 javascript 中,所有位运算符都会将十进制数转换为 32 位整数。它的作用类似于floor 用于正数,ceil 用于负数。在 JavaScript 中,|0~~ 之类的东西经常被用作将数字转换为整数的技巧。

为了解释您看到的溢出,我们可以查看 Javascript 如何将数字转换为 int32 的规范:http://es5.github.io/#x9.5

抽象操作 ToInt32 将其参数转换为 -2^31 到 2^31-1 范围内的 2^32 个整数值之一。这个抽象操作的作用如下:

  1. number 为对输入参数调用 ToNumber 的结果。
  2. 如果 number 为 NaN、+0、-0、+∞ 或 -∞,则返回 +0。
  3. posInt 为 sign(number) * floor(abs(number))。
  4. int32bitposInt 模 2^32;也就是说,一个带正号且幅度小于 2^32 的 Number 类型的有限整数值 k,使得 posInt 和 k 的数学差在数学上是 2^32 的整数倍。李>
  5. 如果int32bit大于等于2^31,返回int32bit - 2^32,否则返回int32bit

因此,要重现此行为,您必须重现此逻辑。

编辑: 以下是 Mozilla 的 Rhino 引擎在 Java 中的操作方式:(根据 user3435580 提供的 github 链接)

public static int toInt32(double d) {
    int id = (int)d;
    if (id == d) {
        // This covers -0.0 as well
        return id;
    }

    if (d != d
        || d == Double.POSITIVE_INFINITY
        || d == Double.NEGATIVE_INFINITY)
    {
        return 0;
    }

    d = (d >= 0) ? Math.floor(d) : Math.ceil(d);

    double two32 = 4294967296.0;
    d = Math.IEEEremainder(d, two32);
    // (double)(long)d == d should hold here

    long l = (long)d;
    // returning (int)d does not work as d can be outside int range
    // but the result must always be 32 lower bits of l
    return (int)l;
}

【讨论】:

  • 我将如何复制19981111156.111113453456754645 | 0-1493725324 可能不会发生它会变得那么大,但以防万一。是的,它似乎在 32 位范围内溢出。在 Java 中 (int)19981111156.111113453456754645 给出 2147483647
  • Java 似乎在最大 int 处截断了值。我已经更新了我的答案来解释(用规范的话)JavaScript 中的这种溢出行为。
  • github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/… 似乎是这样,是的,这就是答案。 toInt32(19981111156.111113453456754645) 变为 -1493725324
猜你喜欢
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 2016-04-12
  • 2018-10-14
  • 1970-01-01
  • 1970-01-01
  • 2017-03-14
相关资源
最近更新 更多