例如
str = 'f01288c2' #a hexadecimal string
bin = str.to_i(16).to_s(2).rjust(str.length + (64 - (str.length % 64)), '0')
因此二进制字符串的大小始终是64的乘法
这里的问题是,str.length
是转换成二进制之前的长度。我需要to_s(2)
之后的字符串长度。如何访问to_s(2)
的返回值?
更新 我想知道是否有单链解决方案。
答案 0 :(得分:4)
单行解决方案将使用Kernel#tap
和str.replace
:
ruby > str = 'f01288c2' #a hexadecimal string
=> "f01288c2"
ruby > bin = str.to_i(16).to_s(2).rjust(str.length + (64 - (str.length % 64)), '0')
=> "0000000000000000000000000000000011110000000100101000100011000010"
ruby > bin = str.to_i(16).to_s(2).tap { |str| str.replace str.rjust(str.length + (64 - (str.length % 64)), '0') }
=> "11110000000100101000100011000010"
答案 1 :(得分:2)
您必须将其拆分为两行:
str = 'f01288c2' #a hexadecimal string
len = str.to_i(16).to_s(2)
bin = len.rjust(str.length + (64 - (str.lenght % 64)), '0')
答案 2 :(得分:2)
您是否需要该值本身,或者您是否需要它来进行结果箱的长度计算?
也许这解决了你的问题(但不是你的答案):
str = 'f01288c2' #a hexadecimal string
bin = "%0*b" % [str.length + (64 - (str.length % 64)),str.to_i(16)]
基于我的其他'answer'以及一些想法,我对问题进行了单元测试并结合了答案。我发现没有正确的单线。在方法my_solution中我至少有一些代码,我的测试说好了。我希望我的测试设计是正确的;)
gem 'test-unit'
require 'test/unit'
def original(str) #from https://stackoverflow.com/questions/6894901/how-to-access-return-value-of-a-method-chain-in-ruby
str.to_i(16).to_s(2).rjust(str.length + (64 - (str.length % 64)), '0')
end
def whitequark_1(str) #accepted: https://stackoverflow.com/questions/6894901/how-to-access-return-value-of-a-method-chain-in-ruby/6894974#6894974
str.to_i(16).to_s(2).tap { |str| str.replace str.rjust(str.length + (64 - (str.length % 64)), '0') }
end
def whitequark_2(str) #accepted: https://stackoverflow.com/questions/6894901/how-to-access-return-value-of-a-method-chain-in-ruby/6894974#6894974
str.to_i(16).to_s(2).rjust(str.length + (64 - (str.length % 64)), '0')
end
def yossi(str) #https://stackoverflow.com/questions/6894901/how-to-access-return-value-of-a-method-chain-in-ruby/6894943#6894943
len = str.to_i(16).to_s(2)
#~ len.rjust(str.length + (64 - (str.lenght % 64)), '0')
len.rjust(str.size + (64 - (str.size% 64)), '0')
end
def my_solution(str) #
size1 = ("%0b" % str.to_i(16).to_s).size
size2 = 64 * ( size1 / 64 + [1, size1 % 64 ].min)
"%0*b" % [size2, str.to_i(16)]
end
#Select the version you want to check
#~ alias :experiment :original #wrong
#~ alias :experiment :yossi
#~ alias :experiment :whitequark_1 #wrong with f01288c2_f01288c2
#~ alias :experiment :whitequark_2 #wrong with f_f01288c2_f01288c2
alias :experiment :my_solution
#Testcases for different Test-setups.
module MyTestcases
def test_binary()
assert_match( /\A[01]+\Z/, @bin)
end
def test_solution()
pend "No solution defined #{@bin}" unless defined? @solution
assert_equal( 0, @solution.size % 64)
assert_equal( @bin.to_i(2), @solution.to_i(2))
assert_equal( @str, @solution.to_i(2).to_s(16))
assert_equal( @solution, @bin)
end
def test_multiply64()
assert_equal( 0, @bin.size % 64, 'no multiply of 64')
end
def test_smallest64()
size = ("%b" % @str.to_i(16)).size
smallestsize = 0
#determine smallest
while smallestsize < size
smallestsize += 64
end
assert_equal( smallestsize, @bin.size, 'not smallest multiply of 64')
end
end
class MyTest_00000001 < Test::Unit::TestCase
def setup
@str = '1' #a hexadecimal string
@bin = experiment(@str)
@solution = "0000000000000000000000000000000000000000000000000000000000000001"
end
include MyTestcases
end
class MyTest_f01288c2 < Test::Unit::TestCase
def setup
@str = 'f01288c2' #a hexadecimal string
@bin = experiment(@str)
@solution = "0000000000000000000000000000000011110000000100101000100011000010"
end
include MyTestcases
end
class MyTest_ff01288c2 < Test::Unit::TestCase
def setup
@str = 'ff01288c2' #a hexadecimal string
@bin = experiment(@str)
@solution = "0000000000000000000000000000111111110000000100101000100011000010"
end
include MyTestcases
end
class MyTest_f01288c2_f01288c2 < Test::Unit::TestCase
def setup
@str = 'f01288c2f01288c2' #a hexadecimal string
@bin = experiment(@str)
@solution = "1111000000010010100010001100001011110000000100101000100011000010"
end
include MyTestcases
end
class MyTest_f_f01288c2_f01288c2 < Test::Unit::TestCase
def setup
@str = 'ff01288c2f01288c2' #a hexadecimal string
@bin = experiment(@str)
@solution = "00000000000000000000000000000000000000000000000000000000000011111111000000010010100010001100001011110000000100101000100011000010"
end
include MyTestcases
end
答案 3 :(得分:1)
也许我错过了什么,但你可以通过这样做很容易地访问to_s(2)的返回值:
r = str.to_i(16).to_s(2)
答案 4 :(得分:1)
在实际代码中,您将使用中间行来分配长度(请参阅@ Yossi的答案),这是正确的方法。现在,如果你想要一种方法来做一个有趣的单行程,那么你可以使用例如Object#as
抽象(在某些情况下实际上相当有用)
class Object
def as
yield self
end
end
str = 'f01288c2'
len, bin = str.to_i(16).to_s(2).as { |len| [len, len.rjust(str.length + (64-(str.length%64)), '0') }
答案 5 :(得分:0)
这不是'回答',而是一个问题 - 对于评论来说有点太长了。
因此二进制字符串的大小始终是64的乘法。
你的str.length +(64 - (str.length%64))应该是64的倍数,所以二进制字符串适合吗?
对于'11f01288c2'(10个字符),它应该是128?对? (64是小,所以你需要128) 但是你的计算结果是64。
我这边有误会吗?
这里是一个代码示例(以及另一个计算的快速版本 - 也许是更好的一个):
str = '11f01288c2' #a hexadecimal string
p (str.length + (64 - (str.length % 64))) #-> 64
p 64 * ((str.length * 8).divmod(64).first + 1) #-> 128
p 64 * ((str.length).divmod(8).first + 1) #-> 128
答案 6 :(得分:0)
我认为你想要的计算是:
(str.length / 64.0).ceil * 64
你的字符串将产生不必要的64 0,这些字符串已经是64长的偶数倍。
您遇到的问题是您尝试将rjust
视为一个块,以便您可以访问其接收器。但是因为它是一个方法,所以它的参数在被调用之前就会被计算出来。因此,将其转换为单行的方法是将其转换,创建一个匿名函数,然后在字符串上调用它:
lambda {|x| x.rjust((x.length / 64.0).ceil * 64, '0')}.call(str.to_i(16).to_s(2))
对我来说实际上有点令人费解的是,没有内置的方法来调用Ruby中的对象上的块,比如tap
但是返回块的结果。 (我错过了什么吗?)
但我们当然可以轻松创建一个:
class Object
def doblock
block_given? ? yield self : self
end
end
那将让我们做(除其他事项外):
str.to_i(16).to_s(2).doblock {|x| x.rjust((x.length / 64.0).ceil * 64, '0')}