Frage

Ich versuche, das Ergebnis eines MD5-Hash in der kürzesten möglichen Zeichenfolge darzustellen. Es scheint eine Verschwendung, nur es sich in ein Hex-String und G bis Z zu vergeuden.

Eine Idee, die ich hatte, den MD5-Hash meiner Eingabe als ein Array von Bytes auszusteigen und BigInt damit zu konstruieren. Ich kann dann toString(36) nennen, und die Zahl als Basis-36 in einer Zeichenkette erhalten (-?[0-9a-z]* kann die Zahl positiv oder negativ sein). Es funktioniert für mich.

Das Problem ist, ich bin nicht sicher, dass ein BigInt mit jedem Byte-Array aufgebaut werden kann, und ich kann es nicht mit Tests beweisen (zumindest nicht in einer angemessenen Art und Weise!). Ich gehe davon aus, denn ich verstehe, dass ein BigInt beliebiger Größe sein kann. Ich kann diese Methode nicht verwenden, bis ich sicher weiß, dass es für alle möglichen Ausgänge zu arbeiten. So kann mir jemand sagen, ob es für alle Eingänge funktionieren wird (oder wie man leicht eine Byte-Array konvertieren, so dass es in der Basis dargestellt werden kann, 36).

Klarstellung : Ich die Umsetzung haben, ich bin über das Verhalten über die gesamte Domäne fragen (das heißt 00000000000000000000000000000000 zu FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

War es hilfreich?

Lösung

Basierend auf Ihrem Feedback über die folgende Implementierung wird einen beliebigen Byte-Array zuverlässig kodieren / dekodieren:

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)
  }

}

Beachten Sie, dass wir ein zusätzliches 0x01 Byte auf den Kopf des Arrays hinzufügen, um Nebenwirkungen zu vermeiden, wobei das Zwei-Komplement des Byte-Array.

EDIT: Die Prüfung, dies zu beweisen beteiligt geführt wird dokumentiert hier: http: // cleverlytitled.blogspot.com/2009/10/scalacheck.html

Andere Tipps

Wäre es nicht Base64-Kodierung kürzer als Base36? Sie können rund um viele Implementierungen finden.

Aber, um tatsächlich die Frage zu beantworten:

  // 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!!")
  }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top