Ruby 中通过进位左旋转

发布于 2024-11-06 04:08:08 字数 374 浏览 1 评论 0原文

我正在尝试在 Ruby 中实现 SHA1,为此我需要通过进位执行左旋转。我编写的代码似乎可以工作 1 轮,但超过 1 轮后它就无法通过我的测试,有人知道为什么吗?

class Integer
  def rotate_left(count, size)
    temp = self

    count.times do
      first_bit = (self & 2 ** size)[size]
      temp = temp << 1
      temp = temp ^ first_bit
      temp = temp ^ (2 ** (size + 1))
    end

    return temp
  end
end

I'm trying to implement SHA1 in Ruby and in order to do so I need to preform a left rotate through carry. The code I've written seems to work for 1 rotation, but any more than that it fails my tests, anybody know why?

class Integer
  def rotate_left(count, size)
    temp = self

    count.times do
      first_bit = (self & 2 ** size)[size]
      temp = temp << 1
      temp = temp ^ first_bit
      temp = temp ^ (2 ** (size + 1))
    end

    return temp
  end
end

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

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

发布评论

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

评论(3

最佳男配角 2024-11-13 04:08:08

我首先检查了 Wikipedia 以确保我理解该操作。看起来你好像失去了你的随身物品。另外,我添加了测试类以确保我得到正确的答案。我不确定您是否想保留进位,因此我注释掉了代码以截断结果。希望这有帮助!

class Integer
    def rotate_left(count, size)
        temp = self
        carry = 0

        count.times do
            temp = temp << 1
            temp = temp | carry
            carry = (temp >> size) & 1
        end

        return temp # & (( 1 << size ) - 1)
    end

end

if __FILE__ == $0 then

    require 'test/unit'

    class TestRotateLeft < Test::Unit::TestCase
        def test_no_rotation
            result = 5.rotate_left(0,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 5, result
            assert_equal 0, carry
        end

        def test_one_rotation
            result = 5.rotate_left(1,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 10, answer
            assert_equal 0, carry
        end

        def test_first_carry
            result = 5.rotate_left(2,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 4, answer
            assert_equal 1, carry
        end

        def test_shift_from_carry
            result = 5.rotate_left(3,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 9, answer
            assert_equal 0, carry
        end

        def test_second_carry
            result = 5.rotate_left(4,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 2, answer
            assert_equal 1, carry
        end

        def test_full_rotation
            result = 5.rotate_left(5,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 5, answer
            assert_equal 0, carry
        end

    end

end

I checked Wikipedia first to make sure I understood the operation. It looks as if you were losing your carry's. Also, I added the test class to make sure I was getting the right answers. I wasn't sure if you wanted to preserve the carried bits or not so I commented out the code to truncate the result. Hope this helps!

class Integer
    def rotate_left(count, size)
        temp = self
        carry = 0

        count.times do
            temp = temp << 1
            temp = temp | carry
            carry = (temp >> size) & 1
        end

        return temp # & (( 1 << size ) - 1)
    end

end

if __FILE__ == $0 then

    require 'test/unit'

    class TestRotateLeft < Test::Unit::TestCase
        def test_no_rotation
            result = 5.rotate_left(0,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 5, result
            assert_equal 0, carry
        end

        def test_one_rotation
            result = 5.rotate_left(1,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 10, answer
            assert_equal 0, carry
        end

        def test_first_carry
            result = 5.rotate_left(2,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 4, answer
            assert_equal 1, carry
        end

        def test_shift_from_carry
            result = 5.rotate_left(3,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 9, answer
            assert_equal 0, carry
        end

        def test_second_carry
            result = 5.rotate_left(4,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 2, answer
            assert_equal 1, carry
        end

        def test_full_rotation
            result = 5.rotate_left(5,4)
            answer = result & 15
            carry = ( result & 16 ) >> 4
            assert_equal 5, answer
            assert_equal 0, carry
        end

    end

end
无法言说的痛 2024-11-13 04:08:08

您使用什么来确定尺寸?例如,如果您尝试进行 4 位旋转,并且将大小设置为 4,则first_bit 计算将获取第 5 位:

 2**4 => 16
 16.to_s(2) => "10000"   

因此索引正常。但在内循环中,您从 self 获取first_bit,而不是temp。所以这只会在第一次时有效。

what are you using for size? If you are trying to do a 4 bit rotation for example, and you set size to 4, then the first_bit calculation is getting the 5th bit:

 2**4 => 16
 16.to_s(2) => "10000"   

So the indexing is Ok. But in the inner loop, you are getting first_bit from self instead of temp. So this will only work the 1st time through.

混吃等死 2024-11-13 04:08:08

我曾经在Ruby中实现了 SHA-256 (使用右旋转)并最终使用这段代码:

class Integer
  def rotate(n=1)
    self >> n | self << (32 - n)
  end
end

您可以将其修改为左旋转:

class Integer
  def lotate(n=1)
    self << n | self >> (32 - n)
  end
end

虽然很难理解......但它有效:)

I once implemented SHA-256 in Ruby (which is using right rotate) and finally used this code:

class Integer
  def rotate(n=1)
    self >> n | self << (32 - n)
  end
end

You can modify it for left rotate:

class Integer
  def lotate(n=1)
    self << n | self >> (32 - n)
  end
end

Although it's very hard to understand... it works :)

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