Поверните налево через перенос в Ruby - PullRequest
4 голосов
/ 09 мая 2011

Я пытаюсь реализовать SHA1 в Ruby, и для этого мне нужно предварительно преобразовать поворот влево с помощью переноса. Код, который я написал, кажется, работает на 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

Ответы [ 3 ]

2 голосов
/ 10 мая 2011

Сначала я проверил Википедию , чтобы убедиться, что я понял операцию.Выглядит так, как будто вы теряете свой керри.Кроме того, я добавил тестовый класс, чтобы убедиться, что получаю правильные ответы.Я не был уверен, хотите ли вы сохранить переносимые биты или нет, поэтому я закомментировал код для усечения результата.Надеюсь, это поможет!

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
0 голосов
/ 09 мая 2011

Я однажды реализовал SHA-256 в 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

Хотя это очень трудно понять ... это работает:)

0 голосов
/ 09 мая 2011

что вы используете для size?Если вы пытаетесь сделать 4-битное вращение, например, и вы установили размер 4, тогда вычисление first_bit получает 5-й бит:

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

Таким образом, индексирование в порядке.Но во внутреннем цикле вы получаете first_bit от self вместо temp.Так что это будет работать только 1 раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...