我可以用任何字节数组(Scala)构造一个BigInt吗?
我试图用尽可能短的字符串来表示MD5哈希的结果。把它变成一个十六进制字符串并让G到Z去浪费似乎是一种浪费。我可以用任何字节数组(Scala)构造一个BigInt吗?
一个想法我已经是让我作为一个字节数组输入的MD5哈希,构建与它BigInt
。然后我可以调用toString(36)
,并获得一个字符串作为基36的数目(-?[0-9a-z]*
,数目可以是正或负)。这个对我有用。
问题是,我不确定BigInt
可以用任何字节数组构建,而且我无法通过测试来证明它(至少不是及时的!)。我认为是这样,因为我知道BigInt可以是任意大小的。我不能使用这种方法,直到我确信它可以用于所有可能的输出。那么,谁能告诉我它是否适用于所有输入(或者如何轻松转换一个字节数组,以便可以用基数36表示)。
澄清:我实现,我问的是行为在整个域(即00000000000000000000000000000000到FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
你上面的反馈大厦下面的实现将可靠的编码/解码任意字节数组:
package blevins.example
object BigIntEncoder {
val radix = 36
implicit def byteArrayToString(ba: Array[Byte]): String = {
new java.math.BigInteger(addByte(ba)).toString(radix)
}
implicit def stringToByteArray(s: String): Array[Byte] = {
stripByte(new java.math.BigInteger(s, radix).toByteArray)
}
def addByte(ba: Array[Byte]): Array[Byte] = {
val h = new Array[Byte](1)
h(0) = 0x01
h ++ ba
}
def stripByte(ba: Array[Byte]): Array[Byte] = {
ba.slice(1,ba.size)
}
}
请注意,我们正在增加一个额外的0x01字节到数组的头部,以避免任何副作用来获取字节数组的二进制补码。
编辑:参与证明了这一点,测试记录在这里:http://cleverlytitled.blogspot.com/2009/10/scalacheck.html
对不起,迟到接受。备用时间项目只能用于业余时间! – Joe 2009-11-07 14:41:57
会不会Base64编码比Base36更短?你可以找到大量的实现。
但是,实际上回答这个问题:
// Make a big randomly-filled byte array
val random = scala.util.Random
val arraySize = 8543
val bytes: Array[Byte] = new Array[Byte](arraySize) // make some big array
random.nextBytes(bytes) // fill it randomly
// Make a BigInt out of it and the corresponding base36 string representation
val bi: BigInt = new BigInt(new java.math.BigInteger(bytes))
val strRep: String = bi.toString(36)
// Make a new BigInt out of the string rep. Does it match?
val bi2: BigInt = new BigInt(new java.math.BigInteger(strRep, 36))
if (bi == bi2) {
println("yippee!!")
}
// Make a new byte array out of the BigInt. Does it match the original array?
val bytes2: Array[Byte] = bi2.toByteArray
if (bytes deepEquals bytes2) {
println("yippee again!!")
}
我把这个放入一个Windows用户可以下载的URL中的文件名。在Windows中混合使用大写字符比它的价值更麻烦。 感谢您的回答,但我问的是能够构建一个BIGINT任何字节数组。我已经实现,我想咨询一下这是在整个一组的字节数组(即从00000000000000000000000000000000到FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) – Joe 2009-10-29 19:35:30
行为,因为你必须执行,测试循环或随机值和你的角落情况下应该是简单的。你会发现,如果前导字节是0x00,而第二个字节不是负数,或者前导字节是0xff,而第二个字节是负数,则会失败。 – 2009-10-30 02:21:13
你形容绝不在整个域工作的实施,但你可以把它用一个SOH填充数组的头工作( 0x01)字节,如下面的答案中所示。 – 2009-10-30 14:21:05