Могу ли я создать BigInt с любым байтовым массивом (Scala)?

StackOverflow https://stackoverflow.com/questions/1645260

Вопрос

Я пытаюсь представить результат хэша MD5 в самой короткой из возможных строк. Кажется пустой тратой просто превратить его в шестнадцатеричную строку и пропустить G через Z.

У меня была одна идея - получить хэш MD5 моего ввода в виде массива байтов и создать из него BigInt . Затем я могу вызвать toString (36) и получить число в виде base-36 в строке ( -? [0-9a-z] * , номер может быть положительным или отрицательным). Это работает для меня.

Проблема в том, что я не уверен, что BigInt может быть создан с любым массивом байтов, и я не могу доказать это с помощью тестирования (по крайней мере, не своевременно!). Я так полагаю, потому что я понимаю, что BigInt может быть произвольного размера. Я не могу использовать этот метод, пока не узнаю наверняка, что он будет работать для всех возможных выходов. Итак, может кто-нибудь сказать мне, будет ли он работать для всех входных данных (или как легко преобразовать байтовый массив, чтобы он мог быть представлен в базе 36).

Разъяснение : у меня есть реализация, я спрашиваю о поведении по всему домену (т.е. от 00000000000000000000000000000000 до FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

Это было полезно?

Решение

Опираясь на ваши отзывы выше, следующая реализация будет надежно кодировать / декодировать произвольный байтовый массив:

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

Другие советы

Разве кодировка 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!!")
  }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top