gpt4 book ai didi

clojure - 右移 32 位整数

转载 作者:行者123 更新时间:2023-12-04 05:44:16 24 4
gpt4 key购买 nike

Clojure 的位移操作似乎都返回 64 位 long 结果,即使对于 32 位 int 参数也是如此。对于 bit-shift-left 来说,这不是一个实质性的问题:

user=> (format "%08x" (unchecked-int (bit-shift-left (unchecked-int 0x12345678) 4)))
"23456780"
user=> (format "%08x" (unchecked-int (bit-shift-left (unchecked-int 0xf2345678) 4)))
"23456780"

然而,对于负数的 unsigned right-shifting 来说,这成为一个问题:
user=> (format "%08x" (unchecked-int (unsigned-bit-shift-right (unchecked-int 0xf2345678) 4)))
"ff234567"

当然,正确答案是 0f234567

在 Clojure 中实现 32 位无符号右移的最有效方法是什么?

最佳答案

这可以通过调用 int clojure.lang.Numbers.unsignedShiftRightInt(int, int) 方法来完成,该方法在 >>> 参数上使用 int ,返回 int 。它目前没有在任何地方公开为函数,但它确实有一个内在的实现(相当于 Java 中的 >>>),您可以直接调用它或包装在您自己的可内联函数中:

(defn unsigned-bit-shift-right-int
{:inline (fn [x n] `(clojure.lang.Numbers/unsignedShiftRightInt ~x ~n))}
[x n]
(clojure.lang.Numbers/unsignedShiftRightInt x n))

无论是否被内联,这都会返回正确的值,但当然通常您希望它被内联。确保参数实际上是原始的 int s 也很好,以便内在函数可以启动。

这是它在 Clojure 1.8 中在两种可能被内联的情况下编译的内容(非内联情况是一个常规的函数调用,没有什么可看的):

内联原始参数:

稍微滥用 count 只是为了说明这一点。注意 iushr 指令。
  • Clojure deftype :
    (deftype Foo [^int x ^int y]
    clojure.lang.Counted
    (count [this]
    (unsigned-bit-shift-right-int x y)))
  • 字节码:
    // Method descriptor #61 ()I
    // Stack: 2, Locals: 1
    public int count();
    0 aload_0 [this]
    1 getfield user.Foo.x : int [19]
    4 aload_0 [this]
    5 getfield user.Foo.y : int [21]
    8 iushr
    9 ireturn
    Line numbers:
    [pc: 0, line: 1]
    [pc: 8, line: 4]
    Local variable table:
    [pc: 0, pc: 9] local: this index: 0 type: user.Foo

  • 内联非原始参数:

    注意 invokestatic clojure.lang.Numbers.unsignedShiftRight… 指令。
  • Clojure 表达式:
    #(format "%08x"
    (clojure.lang.Numbers/unsignedShiftRightInt (unchecked-int 0xf2345678) 4))
  • 字节码:
    // Method descriptor #11 ()Ljava/lang/Object;
    // Stack: 5, Locals: 1
    public java.lang.Object invoke();
    0 getstatic user$eval16141$fn__16142.const__0 : clojure.lang.Var [15]
    3 invokevirtual clojure.lang.Var.getRawRoot() : java.lang.Object [20]
    6 checkcast clojure.lang.IFn [22]
    9 ldc <String "%08x"> [24]
    11 ldc2_w <Long 4063516280> [25]
    14 l2i
    15 ldc2_w <Long 4> [27]
    18 invokestatic clojure.lang.RT.intCast(long) : int [34]
    21 invokestatic clojure.lang.Numbers.unsignedShiftRightInt(int, int) : int [40]
    24 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [46]
    27 invokeinterface clojure.lang.IFn.invoke(java.lang.Object, java.lang.Object) : java.lang.Object [49] [nargs: 3]
    32 areturn
    Line numbers:
    [pc: 0, line: 1]
    [pc: 6, line: 1]
    [pc: 14, line: 1]
    [pc: 21, line: 1]
    [pc: 27, line: 1]
    Local variable table:
    [pc: 0, pc: 32] local: this index: 0 type: java.lang.Object
  • 关于clojure - 右移 32 位整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34914171/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com