JAVA: Hasha ett ord som sedan används för att användas som seed till slumptalsserie

Permalänk
Medlem

JAVA: Hasha ett ord som sedan används för att användas som seed till slumptalsserie

Hej!

Jag har hållit på med Java en hel del men inte med hash-koder och slumptalsserier särskilt mycket.

Det jag behöver är någon form av hash-funktion. Vilken spelar inte så stor roll egentligen då det är en prototyp det handlar om. (MD5 eller liknande är såklart ett plus dock.) Villkoret är att den resulterande hashen skall kunna användas som seed till en slumptalsgenerator. Om jag inte minns fel tar Javas rand-funktion en long som seed, så om man kan generera en hash som sedan kan översättas till en long utan overflow och förlust av data vore detta helt fantastiskt!

Poängen är alltså att ett ord alltid skall generera samma serie med tal.

Om någon kunde hjälpa mig med detta vore det helt fantastiskt underbart bra!

Jag har googlat runt lite och det finns ju Javas inbyggda funktioner, vilket jag inte har något alls emot att använda, men att konvertera något först till en hash, sedan till en long, och sedan använda som seed. Det känns ju som detta borde ha gjorts många gånger tidigare?

Hoppas någon har erfarenhet av detta och kan hjälpa till!

Tack på förhand!

MVH

Johan

Visa signatur

Stek mer! - Flingor - Schampo
Överklockning är är lika överskattat som din dator är överklockad.

Permalänk
Medlem

Beroende på vad du ska ha det till kanske det räcker med "mystring".hashCode()? Då får du en int som du kan stoppa in som seed direkt.

Visa signatur

AK47s for everyone! - Angry mob
Since NaN /= NaN, I think, we should decipher 'NaN' as 'Not a NaN' - Miguel Mitrofanov
(Varför är människan så benägen att tro på Gud?) Antagligen har det lönat sig och evolutionen har drivit fram sådana hjärnor. - Anon

Permalänk
Medlem

Javas inbyggda hashfunktionalitet bygger helt på 128 bitars-summor, vilket inte får plats i en long. Däremot finns det några snabba och enkla hashalgoritmer där ute som man kan använda om man inte behöver någon säkerhet för krockar (vilket du inte verkar behöva?). Nedan använder jag MurmurHash som är snabb och enkel, och ger tillbaka en 32 bitar stor hashsumma.

Det här fungerar troligtvis som du vill:
HashSeed.java

import java.util.Random; public class HashSeed { public static long getSeed(String word) { long l = MurmurHash.hash(word.getBytes(), 1); return l; } public static void main(String[] args) throws Exception { Random r = new Random(); long seed = HashSeed.getSeed("Ordet"); r.setSeed(seed); System.out.println(r.nextInt()); } }

MurmurHash.java, kommer ursprungligen från http://www.getopt.org/murmur/MurmurHash.java

/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * This is a very fast, non-cryptographic hash suitable for general hash-based * lookup. See http://murmurhash.googlepages.com/ for more details. * * <p>The C version of MurmurHash 2.0 found at that site was ported * to Java by Andrzej Bialecki (ab at getopt org).</p> */ public class MurmurHash { public static int hash(byte[] data, int seed) { int m = 0x5bd1e995; int r = 24; int h = seed ^ data.length; int len = data.length; int len_4 = len >> 2; for (int i = 0; i < len_4; i++) { int i_4 = i << 2; int k = data[i_4 + 3]; k = k << 8; k = k | (data[i_4 + 2] & 0xff); k = k << 8; k = k | (data[i_4 + 1] & 0xff); k = k << 8; k = k | (data[i_4 + 0] & 0xff); k *= m; k ^= k >>> r; k *= m; h *= m; h ^= k; } int len_m = len_4 << 2; int left = len - len_m; if (left != 0) { if (left >= 3) { h ^= (int) data[len - 3] << 16; } if (left >= 2) { h ^= (int) data[len - 2] << 8; } if (left >= 1) { h ^= (int) data[len - 1]; } h *= m; } h ^= h >>> 13; h *= m; h ^= h >>> 15; return h; } }

Permalänk
Medlem

Om alla ord är kortare än 12 tecken kan du "fuska" lite och konvertera "ordet" från bas 62 till bas 10 och få ett vanligt tal som får plats i en long. Detta görs med Long.parseLong(ord, 62).

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av bjornie
Javas inbyggda hashfunktionalitet bygger helt på 128 bitars-summor, vilket inte får plats i en long.

hashCode() % ANTAL_LONG_VÄRDEN ?

Visa signatur

www.filipsprogram.tk - lite freeware
"Delight, herregud. Talang är bara förnamnet."

Permalänk
Medlem

Med inbyggda hashfunktionalitet menade jag självklart de klasser som hanterar hashsummor från MD5, SHA, el. likn. Med andra ord java.security.MessageDigest.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av bjornie
Med inbyggda hashfunktionalitet menade jag självklart de klasser som hanterar hashsummor från MD5, SHA, el. likn. Med andra ord java.security.MessageDigest.

Du kan fortfarande (antar jag) köra modulo på dessa hashar, möjligtvis måste du även byta talbas först om den nu känner för att returnera det hela som en sträng.

Permalänk
Medlem

Ja, det går säkert. Men jag skulle ändå föredra att använda MurmurHash än att göra aritmetiska operationer på hashsummor.

Ang. hashCode() vet jag inte riktigt hur de fungerar. Java hanterar ju (som ni säkert vet) strängar lite annorlunda, dom delar minnesrymd vid samma innehåll till en viss gräns - frågan är hur detta påverkar hashCode()? Om dom _inte_ delar minnesrymd, får man ändå ut samma hashsumma? Det känns som att den är unik per strängobjekt och inte på innehållet i strängen, men det är alltså bara spekulationer från min sida.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av bjornie
Ja, det går säkert. Men jag skulle ändå föredra att använda MurmurHash än att göra aritmetiska operationer på hashsummor.

Fördelen med att fulhacka på hashsummor är ju att du slipper bry dig om MurmurHash's licens, om det nu skulle visa sig vara ett problem. Nu råkar den ligga under en trevlig Apache-licens så det spelar ingen större roll i det här fallet, men det kan vara värt att tänka på.

Permalänk
Medlem

Ojojoj! Såhär utförliga och välskrivna svar hade jag verkligen inte förväntat mig! Dessutom på så kort tid!

Jag får verkligen tacka så hemskt mycket! Testade direkt nu att pröva med Murmur hash vilket verkar fungera helt ypperligt! Det enda "problemet" verkar vara att den kan generera negativa heltal, vilket jag inte angav som en begränsning. Och integers kan ju givetvis vara negativa. Men detta enkelt lösas genom att ta beloppet av den resulterade Integern. Dock halveras antalet möjliga tal. Men att randomera endast positiva integer antar jag inte finns, eller? I vilket fall är det ett mycket litet problem...

Tack så hemskt mycket, igen!

Ha en fortsatt strålande dag!

MVH

Johan

EDIT: Men en liten modifikation fungerar det ypperligt även för detta ändamål:

System.out.println(r.nextInt(Integer.MAX_VALUE));

Visa signatur

Stek mer! - Flingor - Schampo
Överklockning är är lika överskattat som din dator är överklockad.