我正在尝试在Ruby中实现SHA1,为了做到这一点,我需要通过carry执行左旋转。我写的代码似乎可以用于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
答案 0 :(得分:2)
我首先检查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
答案 1 :(得分:0)
你在size
使用了什么?例如,如果您尝试进行4位旋转,并将size设置为4,则first_bit计算得到第5位:
2**4 => 16
16.to_s(2) => "10000"
所以索引是好的。但是在内循环中,你从self
获得first_bit而不是temp。所以这只会在第一次通过。
答案 2 :(得分:0)
我曾经实现SHA-256 in Ruby(使用右旋转)并最终使用了此代码:
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
虽然很难理解......但是有效:)