【问题标题】:Left shift into fixnum sign bit左移到 fixnum 符号位
【发布时间】:2020-11-17 09:07:48
【问题描述】:

我正在寻找一种方法将位从正的固定数字转移到符号位置。基本上,我想要的是一种可预测(不是未定义)的方式来执行 fixnum 左移而无需溢出检查。

一个低效的实现如下所示:

(define shift-left
  (lambda (value shift)
    (let ([unsigned-to-signed
       (lambda (value width)
         (let* ([sign-mask (bitwise-arithmetic-shift-left
                1 (- width 1))]
            [sign (bitwise-and value sign-mask)])
           (bitwise-ior
        (bitwise-bit-field value 0 width)
        (- sign))))])
      (unsigned-to-signed
       (bitwise-arithmetic-shift-left value shift)
       (fixnum-width)))))

(shift-left 1 59) ⇒ 576460752303423488
(shift-left 1 60) ⇒ -1152921504606846976
(shift-left 1 61) ⇒ 0

理想情况下,这将编译为单个 CPU 指令(至少对于恒定移位而言;CPU 在处理移位与寄存器一样宽或更宽的方式上有所不同)。

【问题讨论】:

  • 您无法保证一个数字是一个固定数字,或者它将符号存储为它的 msb。 R6RS 将自动为更大的数字腾出更多空间,因为您将其加 1。
  • 我认为这并不重要。 R6RS 库有 (fixnum-width) 并且 fixnum 操作需要二进制补码,因此该过程的行为将是明确定义的。
  • 这可能无济于事,但在 Racket 中,我认为您想要的是来自 racket/unsafe/opsunsafe-fxlshift

标签: scheme chez-scheme r6rs


【解决方案1】:

除非你寻找implementation defined features,否则它不会工作。

在方案中它标准化了tower of arithmetic types,这使得您控制数字表示的内侧非常不方便。

只有在您了解某些实现的内部原理时,您尝试做的事情才有意义,否则您会浪费时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多