Port de générateur Aléatoire de C à Java?
George Marsaglia a écrit un excellent générateur de nombre aléatoire qui est extrêmement rapide, simple, et a beaucoup plus de temps que le nombre de Mersenne Twister. Voici le code avec description:
bon C générateur de nombre aléatoire
Je voulais le port de l'CMWC4096 code Java, mais il utilise plusieurs types de données non signé, donc je ne suis pas sûr de savoir comment le faire correctement. Voici tout le code C:
/* choose random initial c<809430660 and */
/* 4096 random 32-bit integers for Q[] */
static unsigned long Q[4096],c=362436;
unsigned long CMWC4096(void) {
unsigned long long t, a=18782LL;
static unsigned long i=4095;
unsigned long x,r=0xfffffffe;
i = (i+1) & 4095;
t = a*Q[i] + c;
c = (t>>32);
x = t + c;
if (x < c) {
x++;
c++;
}
return (Q[i] = r - x);
}
Quelqu'un peut-port ce de Java? Comment cela fonctionne quand vous avez seulement des nombres signés disponibles?
EDIT: Merci à tous pour les réponses rapides! Pour la première tranche de 100 millions de numéros de code java semble produire le même résultat que le code C. Il est 3 fois plus rapide que Java est java.util.Aléatoire.
public class ComplimentaryMultiplyWithCarryRandom {
/**
* Choose 4096 random 32-bit integers
*/
private long[] Q;
/**
* choose random initial c<809430660
*/
private long c = 362436;
private int i;
public ComplimentaryMultiplyWithCarryRandom() {
Random r = new Random(1);
Q = new long[4096];
//TODO initialize with real random 32bit values
for (int i = 0; i < 4096; ++i) {
long v = r.nextInt();
v -= Integer.MIN_VALUE;
Q[i] = v;
}
i = 4095;
}
int next() {
i = (i + 1) & 4095;
long t = 18782 * Q[i] + c;
c = t >>> 32;
long x = (t + c) & 0xffffffffL;
if (x < c) {
++x;
++c;
}
long v = 0xfffffffeL - x;
Q[i] = v;
return (int) v;
}
}
OriginalL'auteur martinus | 2008-12-29
Vous devez vous connecter pour publier un commentaire.
Pas De Stress!
a=18782
de sorte que le plus grandt
pourrait jamais l'être n'est pas assez grande pour causer signé vs non signé problèmes. Vous auriez de "mise à niveau" le résultat de l'utilisation de Q à une valeur égale à un non signé de 32 bits numéro avant de l'utiliser n'importe où. par exemple, si Q est unint
(signé 32 bits) alors que vous avez à faire cela avant de l'utiliser dans let=a*Q[i]+c
déclaration, par exempleoù cette (((long)Q[i])&0xffffffffL) favorise Q[i] 64-bits # et veille à sa haute 32 bits sont à 0. (edit: REMARQUE: vous devez 0xffffffffL ici. Java n'est pas une bonne chose si vous utilisez 0xffffffff, il semble que cela "optimise" lui-même à la mauvaise réponse & vous obtenez un nombre négatif si Q[i]'s high bit est à 1.)
Vous devriez être en mesure de vérifier cela en exécutant des algorithmes en C++ et Java pour comparer les résultats.
edit: voici une chance. J'ai essayé de courir en C++ et Java pour N=100000; ils les deux match. Toutes mes excuses si j'ai utilisé le mauvais Java idiomes, je suis encore assez nouveau pour Java.
C++:
java: (plus lent que compilé en C++, mais il correspond pour N=100000)
OriginalL'auteur Jason S
La plupart du temps il n'est pas nécessaire d'utiliser de plus gros types numériques pour la simulation des types non signés en Java.
Pour l'addition, la soustraction, la multiplication, la touche maj de gauche, la logique des opérations, de l'égalité
et un casting pour un plus petit type numérique
il n'importe pas si les opérandes sont signés ou non signés,
le résultat sera le même, quel que soit, considéré comme un motif de bits.
Pour passer à la bonne utilisation >> pour la signature, >>> unsigned.
Pour signé un casting pour un plus grand type, tout simplement.
Non signés, de la conversion d'un type plus petit pour une utilisation de longue durée & avec un masque de type long pour le type le plus petit.
E. g., court au long: s & 0xffffL.
Non signés, de la conversion d'un type plus petit pour un int utiliser & avec un masque de type int.
E. g., byte int: b & 0xff.
Sinon faire comme dans l'int de cas et d'appliquer un plâtre sur le dessus.
E. g., octet de court: (court) (b & 0xff).
Pour les opérateurs de comparaison < etc. et de la division, le plus simple est de jeter un plus grand type et de faire l'opération.
Mais il existe également d'autres options, comme par exemple faire des comparaisons après l'ajout d'un décalage adéquate.
Je n'ai pas vu de cette façon, mais vous êtes de droite. Sans le masque le casting est signé, avec le masque de non signé. Habituellement, vous n'avez même pas besoin de faire le cast explicite, comme & avec une valeur appropriée ne l'élargissement.
blogs.oracle.com/darcy/entry/unsigned_api
OriginalL'auteur starblue
Si vous êtes à la mise en œuvre d'un générateur de nombres aléatoires en Java, il est préférable de sous-classe de la java.util.Aléatoire de la classe et de l'emporter sur les protégés prochaine(int) méthode (votre RNG est alors une baisse-dans le remplacement pour java.util.Aléatoire). La prochaine(int) méthode concerne généré de façon aléatoire de bits, pas ce que vales ces bits peut représenter. Les autres (public) méthodes de java.util.Aléatoire l'utilisation de ces bits pour construire aléatoire des valeurs de types différents.
OriginalL'auteur Dan Dyer
Pour obtenir autour de Java manque de unsigned types de généralement de stocker des nombres dans un plus grand type de variable (short mis à niveau vers entiers, entiers à la longue). Puisque vous êtes à l'aide de variables longs ici, vous allez avoir à passer à BigInteger, qui sera probablement épave toute vitesse les gains que vous obtenez de l'algorithme.
Votre interprétation de
long
à l'origine, le code C est incorrect. Il fait référence à un entier de 32 bits de type, ce qui correspond àint
en Java.OriginalL'auteur Bill the Lizard
Juste un petit point de référence qui peut (ou pas) de vous aider, j'ai trouvé ce lien:
http://darksleep.com/player/JavaAndUnsignedTypes.html
OriginalL'auteur Joel Marcey
Vous pouvez utiliser des nombres signés fourni les valeurs ne déborde pas...par exemple, de long en java 64 bits entier signé. Toutefois, l'intention de cet algorithme semble être d'utiliser une version 64 bits de valeur non signée, et si oui, je pense que vous serait hors de la chance avec les types de base.
Vous pouvez utiliser le multiprecision entiers fournis dans les bibliothèques de classes java (BigInteger). Ou vous pouvez mettre en place votre propre 64 bits type non signé comme un Objet contenant deux java aspire à représenter le moins important et le plus significatif des mots (mais vous auriez à mettre en œuvre les opérations arithmétiques de base vous-même dans la classe).
Oups - vous avez raison! Qui vous montre combien de temps il est comme je voulais utiliser MP ints. Je vais corriger ça maintenant.
Votre interprétation de
long
à l'origine, le code C est incorrect. Il fait référence à un entier de 32 bits de type, ce qui correspond àint
en Java.Fait intéressant, la vieille lien vers java.les mathématiques.Bignum, montre que c'est une fusion de deux BigInteger et BigDecimal. Je suis reconnaissant pour la conception finale, ce qui est beaucoup plus claire. De Plus, j'utilise BigInteger souvent, mais BigDecimal très rarement, il est donc bon que je n'ai pas besoin de prêter attention à la BigDecimal des méthodes de travail avec BigInteger.
OriginalL'auteur frankodwyer