Pollux :
Je te remercie et je t'autorise à relire mon message![]()
Bon, je réexplique : si on prend n=64 au lieu de n=56, on perd log2(64/56)=0.2 bits d'entropie. Et on a 32 bits, donc ça va vraiment pas être la mort de perdre 0.2 bits
unsigned long randnum=255-(unsigned char)(peekIO(0x600017)-1); if (!AMS_1xx || *(unsigned short *)0x32==(('R'<<8)+'O')) randnum+=(*((volatile unsigned long*)(_rom_call_addr(4FC))))*((HW_VERSION == 2)?53:79); srand(randnum);
Pollux :
Pollux :
1) ça ne change qqch qu'à partir de quelle version d'AMS ?
2) ça ne sert strictement à _rien_ de vouloir gagner 0.2/32 = 1/160 < 1% de données aléatoires d'initialisation en plus, alors que la routine va grossir de plusieurs dizaines d'octets (probablement pas mal : test du hardware, multiplication par un 'long')
2.4.1 When "random", it must be capable of generating a uniformly random integer in the range 1 <= x <= n, for any value 1 <= n <= 32767. Any method can be used for this (for instance, using the host computer's clock time in milliseconds). The uniformity of randomness should be optimised for low values of n (say, up to 100 or so) and it is especially important to avoid regular patterns appearing in remainders after division (most crudely, being alternately odd and even).
2.4.2 The generator is switched into "predictable" state with a seed value. On any two occasions when the same seed is sown, identical sequences of values must result (for an indefinite period) until the generator is switched back into "random" mode. The generator should cope well with very low seed values, such as 10, and should not depend on the seed containing many non-zero bits.
Kevin Kofler
:Pollux :
Je ne vois pas ce qu'il y a de drôle dans ce que je dis. Mon algorithme(*) est mathématiquement correct (distribution équiprobable, application surjective sur l'anneau Z/232Z entier)
2) ça ne sert strictement à _rien_ de vouloir gagner 0.2/32 = 1/160 < 1% de données aléatoires d'initialisation en plus, alors que la routine va grossir de plusieurs dizaines d'octets (probablement pas mal : test du hardware, multiplication par un 'long')Je ne suis pas d'accord.
Et enfin, ton calcul est faux. Avec ton "optimisation", sur HW2, on perd (2^32-2^26*53)/2^32=0,17..., c'est-à-dire plus de 17%, des nombres aléatoires possibles!
Oui, à condition de remplacer le randomize par ma routine. (Le randomize actuel ne vérifie pas du tout les critères d'uniformité. Celui de Pollux non plus, d'ailleurs, donc encore une raison de le rejeter: ce n'est pas conforme au standard C. )
it is especially important to avoid regular patterns appearing in remainders after division (most crudely, being alternately odd and even).
j'ai de bonnes raisons de penser que random()&1 n'est pas si aléatoire que ça
multiplication par 0x41C64E6D et addition de 12345, le tout modulo 2^32
Pollux
:Kevin Kofler
:Pollux :
Je ne vois pas ce qu'il y a de drôle dans ce que je dis. Mon algorithme(*) est mathématiquement correct (distribution équiprobable, application surjective sur l'anneau Z/232Z entier)
Mais oui, bien sûr![]()
Tu sais qu'il faut 20 jours avant de décrire tout ça? Tu sais que s'il y a un reset entre temps ta jolie théorie tombe à l'eau? Et tu sais que à moins de l'utiliser 20 jours après au 50è de milliseconde près, ça n'arrivera _jamais_? (je suis même prêt à prendre les paris).
Et tu sais aussi que le générateur aléatoire que vous utilisez est très perfectible, et que ce serait certainement une meilleure idée d'améliorer ça plutôt que de rajouter un cinquième de bit dans le générateur aléatoire? (notamment, j'ai de bonnes raisons de penser que random()&1 n'est pas si aléatoire que ça)
Et enfin, ton calcul est faux. Avec ton "optimisation", sur HW2, on perd (2^32-2^26*53)/2^32=0,17..., c'est-à-dire plus de 17%, des nombres aléatoires possibles!Tu parles en nombres de seeds possibles, je parle en shannon.
Une clé 1025 bits n'est pas 2 fois meilleure qu'une clé 1024 bit
Oui, à condition de remplacer le randomize par ma routine. (Le randomize actuel ne vérifie pas du tout les critères d'uniformité. Celui de Pollux non plus, d'ailleurs, donc encore une raison de le rejeter: ce n'est pas conforme au standard C. )
Relis. Le standard C ne demande pas que la seed (32 bits) soit choisi uniformément, ce n'est obligatoire que pour un nombre aléatoire généré (15 bits). Ca n'a vraiment rien à voir
Et très sincèrement, une plateforme utilisant un long (de 31 bits) n'aurait aucun handicap de ce point de vue-là
Lily
:it is especially important to avoid regular patterns appearing in remainders after division (most crudely, being alternately odd and even).j'ai de bonnes raisons de penser que random()&1 n'est pas si aléatoire que ça?
Pollux :
La modification de la seed est :multiplication par 0x41C64E6D et addition de 12345, le tout modulo 2^32
puis on divise par 2^8
Si tu considères la seed modulo 2^8, c'est une multiplication par 0x6D et addition de 57. Bref, périodicité de 256. C'est vraiment autrement plus grave que le fait que la seed soit initialement sur 31 bits (j'arrondis à l'inférieur pour faire plaisir à Kevin) et pas sur 32 bits.
Pollux
: Et puis d'ailleurs, tant qu'on est dans les défauts de cette algorithme, on n'utilise pas les 9 bits de poids fort de la seed...
Kevin Kofler
:PolluxTout ceci n'a rien à voir avec l'uniformité ou non de la distribution.
:Kevin Kofler
:Pollux :
Je ne vois pas ce qu'il y a de drôle dans ce que je dis. Mon algorithme(*) est mathématiquement correct (distribution équiprobable, application surjective sur l'anneau Z/232Z entier)
Mais oui, bien sûr![]()
Tu sais qu'il faut 20 jours avant de décrire tout ça? Tu sais que s'il y a un reset entre temps ta jolie théorie tombe à l'eau? Et tu sais que à moins de l'utiliser 20 jours après au 50è de milliseconde près, ça n'arrivera _jamais_? (je suis même prêt à prendre les paris).
Et mes calculatrices tournent facilement 20 jours sans reset.
Et tu sais aussi que le générateur aléatoire que vous utilisez est très perfectible, et que ce serait certainement une meilleure idée d'améliorer ça plutôt que de rajouter un cinquième de bit dans le générateur aléatoire? (notamment, j'ai de bonnes raisons de penser que random()&1 n'est pas si aléatoire que ça)
* On utilise le même algorithme que pratiquement tout le monde. (Va lire les sources de newlib et semblables...)
Et enfin, ton calcul est faux. Avec ton "optimisation", sur HW2, on perd (2^32-2^26*53)/2^32=0,17..., c'est-à-dire plus de 17%, des nombres aléatoires possibles!Tu parles en nombres de seeds possibles, je parle en shannon.
Une clé 1025 bits n'est pas 2 fois meilleure qu'une clé 1024 bitSi, il faut 2 fois plus de temps pour la cracker!
Démontre-moi (mathématiquement) que ton seed satisfait cette condition... Je pense que tu n'y arriveras pas, parce que c'est vraisemblablement faux. (Uniforme veut bien dire uniforme, et pas uniforme ±10% ou un truc du style.)Oui, à condition de remplacer le randomize par ma routine. (Le randomize actuel ne vérifie pas du tout les critères d'uniformité. Celui de Pollux non plus, d'ailleurs, donc encore une raison de le rejeter: ce n'est pas conforme au standard C. )
Relis. Le standard C ne demande pas que la seed (32 bits) soit choisi uniformément, ce n'est obligatoire que pour un nombre aléatoire généré (15 bits). Ca n'a vraiment rien à voir
Et très sincèrement, une plateforme utilisant un long (de 31 bits) n'aurait aucun handicap de ce point de vue-làOù est le rapport?
LilyN'oublie pas que les derniers 8 bits du seed sont jetés quand le résultat est retourné (tout comme les premiers). (Le seed, lui, les garde évidemment.)
:it is especially important to avoid regular patterns appearing in remainders after division (most crudely, being alternately odd and even).j'ai de bonnes raisons de penser que random()&1 n'est pas si aléatoire que ça?
Kevin Kofler
:Pollux :
La modification de la seed est :multiplication par 0x41C64E6D et addition de 12345, le tout modulo 2^32
puis on divise par 2^8
Si tu considères la seed modulo 2^8, c'est une multiplication par 0x6D et addition de 57. Bref, périodicité de 256. C'est vraiment autrement plus grave que le fait que la seed soit initialement sur 31 bits (j'arrondis à l'inférieur pour faire plaisir à Kevin) et pas sur 32 bits.
Plusieurs erreurs:
1. On divise un modulo 232 par 28, il reste 224 comme modulo, pas 28.
2. Même cela n'est pas valable parce que le nombre par lequel on multiplie et le nombre qu'on ajoute ne sont pas divisibles par 28. Tu ne peux simplifier mod(a*x+b,232)/28 en mod((a/28)*x+b/28,224) que si a et b sont divisibles par 8. Tu ne peux pas faire ça avec des divisions euclidiennes à reste non nul.
3. Pour illustrer mon 2., un petit contre-exemple:
12345=0x3039
0x41C64E*0x3+0x30=0xC5531A (0x41C64E6D*0x3+0x3039)>>8=0xC5531B
Pollux
: Et puis d'ailleurs, tant qu'on est dans les défauts de cette algorithme, on n'utilise pas les 9 bits de poids fort de la seed...
Martial Demolins :
lol t'aime pas gacher des pixels de texte pour rien toi
Pollux
: Carrément pas : ça veut dire que seule la quasi-injectivité importe, pas la quasi-surjectivité (et donc, il vaudrait mieux prendre 128 pour que ça marche parfaitement bien sur HW2).
Sauf que tu ne les lances pas périodiquement tous les 20 jours avec une précision extrême, donc tu es sûr que tu ne joueras pas à la même partie de Backgammon...
* On utilise le même algorithme que pratiquement tout le monde. (Va lire les sources de newlib et semblables...)
Une clé 1025 bits n'est pas 2 fois meilleure qu'une clé 1024 bitSi, il faut 2 fois plus de temps pour la cracker!
On a quand même des algorithmes non exponentiels pour ça : O(exp((64/9.n)^(1/3).ln(n)^(2/3))) Le quotient entre n=1025 et n=1024 n'est que de 3%, donc arrête de pipoter. Et si tu pipotes pour un truc aussi classique que la factorisation de nombres premiers, alors je ne sais que trop quoi penser quant à ta crédibilité dans cette affaire
Démontre-moi (mathématiquement) que ton seed satisfait cette condition... Je pense que tu n'y arriveras pas, parce que c'est vraisemblablement faux. (Uniforme veut bien dire uniforme, et pas uniforme ±10% ou un truc du style.)![]()
C'est évident qu'un seed "uniforme +/- 10%" va, si on le hashe correctement pour avoir une valeur 16 bits, être pris complètement uniformément (+/- 10%/2^16 soit 0.000015. En pratique, on a besoin de plus de 16 bits pour ne pas avoir de cycles, mais tu vois l'idée.
Le rapport, c'est que ma méthode a une image de cardinal un peu plus de 2^31 et pas exactement 2^32. Donc c'est comme si j'utilisais un signed long et pas un unsigned. Pourtant le standard n'interdis pas d'utiliser un signed long pour ça...Et très sincèrement, une plateforme utilisant un long (de 31 bits) n'aurait aucun handicap de ce point de vue-làOù est le rapport?
Oui, les bits de poids faibles, et?LilyN'oublie pas que les derniers 8 bits du seed sont jetés quand le résultat est retourné (tout comme les premiers). (Le seed, lui, les garde évidemment.)
:it is especially important to avoid regular patterns appearing in remainders after division (most crudely, being alternately odd and even).j'ai de bonnes raisons de penser que random()&1 n'est pas si aléatoire que ça?
Pollux :
Tu es gentil, mais tu vas encore essayer de relire mon message : tu prends modulo 2^8 (hum, en fait c'est modulo 2^9 parce qu'il faut aussi un bit pour la valeur du rand()&1), je ne te parle pas de diviser par 2^8...
Ah oui, ce sont 9 bits qui sont jetés à gauche et pas 8 parce que le standard veut que ce soit <=32767. Ce n'est pas un défaut.??? Ca veut dire que la seed n'a que 2^23 valeurs possibles, c'est un gros gros défaut (plus exactement, on peut quotienter par 0x800000.Z sans changer la valeur finale)
Kevin Kofler
:Pollux
: Carrément pas : ça veut dire que seule la quasi-injectivité importe, pas la quasi-surjectivité (et donc, il vaudrait mieux prendre 128 pour que ça marche parfaitement bien sur HW2).
Non...
Sauf que tu ne les lances pas périodiquement tous les 20 jours avec une précision extrême, donc tu es sûr que tu ne joueras pas à la même partie de Backgammon...... parce que cet argument n'est pas valable, tu réduis le nombre de parties possibles de 17% et c'est un fait indéniable.
* On utilise le même algorithme que pratiquement tout le monde. (Va lire les sources de newlib et semblables...)
D'ailleurs, il se trouve même en "EXAMPLE" dans le standard C. C'est à la lettre le même que dans TIGCCLIB (à part que celui de TIGCCLIB est en assembleur 68k). Il y a même la division par 65536 et le modulo par 32768. C'est de là que toutes les implémentations le recopient.
Une clé 1025 bits n'est pas 2 fois meilleure qu'une clé 1024 bitSi, il faut 2 fois plus de temps pour la cracker!
On a quand même des algorithmes non exponentiels pour ça : O(exp((64/9.n)^(1/3).ln(n)^(2/3))) Le quotient entre n=1025 et n=1024 n'est que de 3%, donc arrête de pipoter. Et si tu pipotes pour un truc aussi classique que la factorisation de nombres premiers, alors je ne sais que trop quoi penser quant à ta crédibilité dans cette affaire
1. C'est quand-même exponentiel en principe. 2. Qui t'a dit que je parlais de clés asymétriques à clé publique connue? Si on parle de clés symétriques, ou de clés asymétriques à clé publique inconnue (ce qui revient à peu près au même), ton argument ne vaut plus rien.
Démontre-moi (mathématiquement) que ton seed satisfait cette condition... Je pense que tu n'y arriveras pas, parce que c'est vraisemblablement faux. (Uniforme veut bien dire uniforme, et pas uniforme ±10% ou un truc du style.)![]()
C'est évident qu'un seed "uniforme +/- 10%" va, si on le hashe correctement pour avoir une valeur 16 bits, être pris complètement uniformément (+/- 10%/2^16 soit 0.000015. En pratique, on a besoin de plus de 16 bits pour ne pas avoir de cycles, mais tu vois l'idée.
1. Je te parle de "uniforme ±10%" après tous les calculs.
2. Si le standard dit "uniforme", ça veut dire ce que ça veut dire. C'est-à-dire que même "uniforme ±10-1000000%" ne convient pas, parce que ce n'est pas uniforme!!!
Le problème est que ta distribution de seeds n'est pas équiprobable. Il y a des seeds qui ne sont pas utilisés et d'autres qui sont utilisés en double (enfin, pour être précis, c'est soit l'un soit l'autre en fonction de la version matérielle). Si on fait ça sur 31 bits en équiprobable, c'est autre chose!Le rapport, c'est que ma méthode a une image de cardinal un peu plus de 2^31 et pas exactement 2^32. Donc c'est comme si j'utilisais un signed long et pas un unsigned. Pourtant le standard n'interdis pas d'utiliser un signed long pour ça...Et très sincèrement, une plateforme utilisant un long (de 31 bits) n'aurait aucun handicap de ce point de vue-làOù est le rapport?
Et ça réduit de loin le problème de la période.Oui, les bits de poids faibles, et?LilyN'oublie pas que les derniers 8 bits du seed sont jetés quand le résultat est retourné (tout comme les premiers). (Le seed, lui, les garde évidemment.)
:it is especially important to avoid regular patterns appearing in remainders after division (most crudely, being alternately odd and even).j'ai de bonnes raisons de penser que random()&1 n'est pas si aléatoire que ça?
Pollux :
Tu es gentil, mais tu vas encore essayer de relire mon message : tu prends modulo 2^8 (hum, en fait c'est modulo 2^9 parce qu'il faut aussi un bit pour la valeur du rand()&1), je ne te parle pas de diviser par 2^8...
Ah, tu parles du dernier bit... Ben, on fait notre possible pour qu'il soit varié. Il me semble bien que la période soit la plus longue possible pour une application affine en modulo. Et c'est pour ça que si tu prends un random(2), il va prendre le premier bit (non-jeté), pas le dernier.
En tout cas, ça fait en sorte que ton idée d'"optimisation" du calcul du seed jette même plus de 17% des seeds possibles!Ah oui, ce sont 9 bits qui sont jetés à gauche et pas 8 parce que le standard veut que ce soit <=32767. Ce n'est pas un défaut.??? Ca veut dire que la seed n'a que 2^23 valeurs possibles, c'est un gros gros défaut (plus exactement, on peut quotienter par 0x800000.Z sans changer la valeur finale)
Remarks
It is dangerous to rely on the ANSI C random number routines, as some
implementations of these are very poor. This has made some games (in particular, 'Balances') unwinnable on some Unix ports of Zip.
(Pollux, tu peux t'amuser à démonter ses algorithmes si tu as envie.)
extern word random1; extern word random2; word temp; temp = random1 << 1; random1 = random2; if (random2 & 0x8000) ++temp; random2 ^= temp; if (num) store(((word)(random2 & 0x7FFF) % num) + 1); else store(0);