如何将十六进制数转换为带'C4D81633'
符号的 2 的补码,即'-992471501'
使用 Ruby?我试过
['C4D81633'.scan(/[0-9a-f]{2}/i).reverse.join].pack('H*').unpack('l')
但是当我输入长度小于 8 个字符时,上面的代码不能正常工作。
如何将十六进制数转换为带'C4D81633'
符号的 2 的补码,即'-992471501'
使用 Ruby?我试过
['C4D81633'.scan(/[0-9a-f]{2}/i).reverse.join].pack('H*').unpack('l')
但是当我输入长度小于 8 个字符时,上面的代码不能正常工作。
否定运算符 ( -
) 已经做了一个二的恭维:
p (-0x1234).to_s(16) # => "-1234"
问题在于 Ruby 的 to_s,它注意到它被否定,并以我们几乎总是想要的方式输出它——用减号。
但是,如果我们屏蔽否定值,我们将让 Ruby 做我们想做的事情:
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"
我建议尽可能使用实际数字。所以,拿你的“字符串化的十六进制数字”,把它转换成一个实际的整数。(所以,正如其他人所建议的那样;'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
了更多可扩展性。您可以覆盖预期的位以进行高级补充。
首先使用String#rjust
你的输入怎么样?
['C4D81633'.rjust(8,'0').scan(/[0-9a-f]{2}/i).reverse.join].pack('H*').unpack('l')
这样,您总是有 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