예를 들어 'C4D81633'
의 16 진수를 부호있는 2의 보수로 변환하려면 어떻게합니까? 예 : '-992471501'
? 나는 16 진수로 부호가있는 2의 보수
['C4D81633'.scan(/[0-9a-f]{2}/i).reverse.join].pack('H*').unpack('l')
을 시도했지만 나는 8 자 이하 길이의 입력을 줄 때 위의 코드는 잘 작동하지 않습니다.
예를 들어 'C4D81633'
의 16 진수를 부호있는 2의 보수로 변환하려면 어떻게합니까? 예 : '-992471501'
? 나는 16 진수로 부호가있는 2의 보수
['C4D81633'.scan(/[0-9a-f]{2}/i).reverse.join].pack('H*').unpack('l')
을 시도했지만 나는 8 자 이하 길이의 입력을 줄 때 위의 코드는 잘 작동하지 않습니다.
나는 인터넷 검색을 한 후 답을 발견 (귀하의 의견은 8 자리보다 긴 경우를 제외하고) 8 개 진수 숫자를 가지고 ... 나는 다음과 방법으로 추가
def convert_to_signed_twos_complement(integer_value, num_of_bits)
length = num_of_bits
mid = 2**(length-1)
max_unsigned = 2**length
(integer_value >= mid) ? integer_value - max_unsigned : integer_value
end
hex_to_convert = 'C4D81633'
convert_to_signed_twos_complement(hex_to_convert.hex, 16)
Note: the num_of_bits in method denote the max bit size of the binary you want
먼저 String#rjust
을 입력에 사용하는 것이 어떻습니까?
['C4D81633'.rjust(8,'0').scan(/[0-9a-f]{2}/i).reverse.join].pack('H*').unpack('l')
이 방법, 당신은 항상
부정 연산자 (-
는) 이미 않는 두 가지의 칭찬 :
p (-0x1234).to_s(16) # => "-1234"
문제는 Ruby의 to_s입니다. Ruby의 to_s는 부정적이라는 것을 알게되고 거의 항상 원하는 방식으로 출력합니다. 빼기 기호가 있습니다.
p (-0x1234 & 0xffff).to_s(16) # => "edcc"
을 그럼 모두 함께 넣어 보자 : 나는 실제 작업을하는 것이 좋습니다
def negate(n, num_bits)
mask = (1 << num_bits) - 1
-n & mask
end
def negate_string(s, num_bits)
negate(s.hex, num_bits).to_s(16)
end
p negate_string("C4D81633", 32) # "3b27e9cd"
을 우리는 부정 값을 마스크 경우
하지만, 우리는 루비가 우리가 원하는 것을 할거야 가능할 때 전화 번호. 따라서 "문자열 화 된 16 진수"를 가져 와서 실제 정수로 변환하십시오. (다른 사람들이 제안한대로, 'C4D81633'.hex
). 나는이 방법을 몇 번 반복했다. 첫 번째는 @ shivashankar의 것이며 다른 하나는 속도 향상입니다. 블랙 박스로 만들고 싶다면 마지막으로 성능을 얻으십시오. 여기
def signed_twos_complement(integer_value, num_bits)
length = num_bits
mid = 2**(length-1)
max_unsigned = 2**length
(integer_value >= mid) ? integer_value - max_unsigned : integer_value
end
def signed_twos_complement2(i)
-(-i & (2**i.to_s(2).length)-1)
end
def signed_twos_complement3(i)
-(-i & (2**i.bit_length)-1)
end
def signed_twos_complement4(i, bits=i.bit_length)
-(-i & (2**bits)-1)
end
# Run chunk below in irb or pry to try benchmarking for yourself
require 'benchmark'
n = 9000000
a = Array.new(n) { rand(1...n) };
Benchmark.bm do |x|
x.report { a.each { |z| signed_twos_complement(z, z.to_s(2).length) } }
x.report { a.each { |z| signed_twos_complement(z, z.bit_length) } }
x.report { a.each { |z| signed_twos_complement2(z) } }
x.report { a.each { |z| signed_twos_complement3(z) } }
x.report { a.each { |z| signed_twos_complement4(z) } }
end
내 벤치 마크 실행에서
user system total real
6.250000 0.040000 6.290000 ( 6.355923)
2.290000 0.010000 2.300000 ( 2.347434)
5.840000 0.040000 5.880000 ( 5.943748)
2.160000 0.010000 2.170000 ( 2.223785)
2.160000 0.020000 2.180000 ( 2.218012)
편집 내 결과입니다 : 나는 좀 더 확장 될 signed_twos_complement4
을 추가했다. 고급 보완을 위해 원하는 비트를 무시할 수 있습니다.
나는 작은 문자열 (예 : 'EC'는 -20으로 반환 됨)에서 작동하므로이 방법이 마음에 듭니다. – shivashankar