Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

probleme

23 réponses
Avatar
eyaarmy
Bonjour, désoler pour le dérangement
je suis en train de créer jeu 2D isométrique sur SDL en c avec generation des énigmes
mais je suis bloqué comment faire pour affficher des images aléatoire sur SDL en c ..
et merci beaucoup

10 réponses

1 2 3
Avatar
Benoit Izac
Bonjour,
Le 02/04/2018 à 11:04, Marc Espie a écrit dans le message
<p9srm0$1e24$ :
Typiquement, regarde les generateurs pseudo-aleatoires congruents.
Tu verras qu'il ne faut jamais faire % N, mais passer en flottant
et diviser par RAND_MAX, multiplier par N et arrondir...

Là, j'avoue que je ne comprends pas pourquoi ce serait mieux que % N ;
bien au contraire, si je reprends l'exemple avec RAND_MAX et N et
que je joue un peu avec Python (je multiplie par N-1 sinon on se
retrouve avec N alors que l'on veut un nombre dans l'intervalle
[0, N[) :

T'as regarde ce que c'etait qu'un generateur pseudo-aleatoire congruent ?

De ce que j'en comprends, c'est une suite où le prochain élément dépend
du précédent avec la formule X_n+1 = (a * X_n + c) % m ; a, c et m étant
choisi avec précaution.
On a donc dans le meilleur des cas m éléments qui si répètent, dans le
pire des cas X_n+1 == X_n et on se retrouve avec un seul élément...
typiquement c'est un machin sur lequel faire %N va te donner une periode
d'au plus N.

Si je comprends bien tu ne parles plus du N de la discussion précédente
mais du m de la formule ci-dessous, c'est bien cela ?
Par exemple, tirer a pile ou face avec un pseudo-aleatoire congruent, a
coup de %2, va te donner au mieux 0 1 0 1 0 1.

En tout cas j'ai regardé le code d'arc4random_uniform dans ta paroisse
et il fait la même chose que ce que j'ai proposé en enlevant le bas de
l'intervalle alors que j'enlevais le haut. Bien sûr il n'utilise pas
random() mais arc4random(). Du coup, je ne comprends toujours pas ta
remarque qu'il ne faut jamais faire % N.
En tout cas, c'est impossible de faire confiance a un bete rand()/random()
"portable" si tu veux un pseudo-aleatoire de qualite decente...

Sans doute, mais là on parle d'afficher une photo au hasard dans un jeu,
il faut donc relativiser.

Non. On commence avec l'affichage d'une photo au hasard d'un jeu, et puis
on passe a autre chose. Ou bien quelqu'un va tomber sur ce code et le
repomper pour autre chose.
On parle ici d'un probleme connu et regle depuis des annees. Je vois zero
raison de ne pas faire les choses correctement. C'est pas comme si c'etait
beaucoup plus complique. Le code necessaire existe deja et peut s'utiliser
sans souci (oui ca existe sous licence BSD, donc tu peux en faire ce que
tu veux, meme pour utilisation commerciale)

Bien mon capitaine !
--
Benoit Izac
Avatar
espie
In article , Benoit Izac wrote:
Bonjour,
Le 02/04/2018 à 11:04, Marc Espie a écrit dans le message
<p9srm0$1e24$ :
Typiquement, regarde les generateurs pseudo-aleatoires congruents.
Tu verras qu'il ne faut jamais faire % N, mais passer en flottant
et diviser par RAND_MAX, multiplier par N et arrondir...

Là, j'avoue que je ne comprends pas pourquoi ce serait mieux que % N ;
bien au contraire, si je reprends l'exemple avec RAND_MAX et N et
que je joue un peu avec Python (je multiplie par N-1 sinon on se
retrouve avec N alors que l'on veut un nombre dans l'intervalle
[0, N[) :

T'as regarde ce que c'etait qu'un generateur pseudo-aleatoire congruent ?

De ce que j'en comprends, c'est une suite où le prochain élément dépend
du précédent avec la formule X_n+1 = (a * X_n + c) % m ; a, c et m étant
choisi avec précaution.
On a donc dans le meilleur des cas m éléments qui si répètent, dans le
pire des cas X_n+1 == X_n et on se retrouve avec un seul élément...
typiquement c'est un machin sur lequel faire %N va te donner une periode
d'au plus N.

Si je comprends bien tu ne parles plus du N de la discussion précédente
mais du m de la formule ci-dessous, c'est bien cela ?

Non, je parle toujours du N de la discussion precedente. Revise ton
arithmetique modulaire.
Par exemple, tirer a pile ou face avec un pseudo-aleatoire congruent, a
coup de %2, va te donner au mieux 0 1 0 1 0 1.

En tout cas j'ai regardé le code d'arc4random_uniform dans ta paroisse
et il fait la même chose que ce que j'ai proposé en enlevant le bas de
l'intervalle alors que j'enlevais le haut. Bien sûr il n'utilise pas
random() mais arc4random(). Du coup, je ne comprends toujours pas ta
remarque qu'il ne faut jamais faire % N.

Ben evidemment qu'arc4random "marche"...
Je dis depuis le debut que tu ne sais pas quel algo est utilise par random().
La qualite des generateurs pseudo-aleatoires traditionnels que ce soit
rand() ou random(), n'est aucunement garantie. Ca peut tres bien etre des
generateurs pseudo-congruents, ou une autre horreur, sur laquelle %N va
merder de facon catastrophique.
Avatar
Benoit Izac
Bonjour,
Le 02/04/2018 à 15:06, Marc Espie a écrit dans le message
<p9t9tj$1i3v$ :
Non, je parle toujours du N de la discussion precedente. Revise ton
arithmetique modulaire.

Désolé, je ne comprends pas le message que tu souhaites faire passer, et
vu que tu fais tout pour ne pas l'expliquer simplement en décrivant ce
qui ne cloche, j'abandonne.
Par exemple, tirer a pile ou face avec un pseudo-aleatoire congruent, a
coup de %2, va te donner au mieux 0 1 0 1 0 1.

En tout cas j'ai regardé le code d'arc4random_uniform dans ta paroisse
et il fait la même chose que ce que j'ai proposé en enlevant le bas de
l'intervalle alors que j'enlevais le haut. Bien sûr il n'utilise pas
random() mais arc4random(). Du coup, je ne comprends toujours pas ta
remarque qu'il ne faut jamais faire % N.

Ben evidemment qu'arc4random "marche"...
Je dis depuis le debut que tu ne sais pas quel algo est utilise par random().
La qualite des generateurs pseudo-aleatoires traditionnels que ce soit
rand() ou random(), n'est aucunement garantie. Ca peut tres bien etre des
generateurs pseudo-congruents, ou une autre horreur, sur laquelle %N va
merder de facon catastrophique.

Et toi depuis le début tu m'expliques que la fonction random() est
pourrie alors que je suis intervenu dans la discussion juste pour
fournir une parade à la répartition qui était biaisée par le modulo.
random() était la fonction utilisée dans le message auquel je répondais,
arc4random() aurait été utilisée, ça n'aurait rien changé à la
problématique sur laquelle je répondais.
--
Benoit Izac
Avatar
espie
In article , Benoit Izac wrote:
Bonjour,
Le 02/04/2018 à 15:06, Marc Espie a écrit dans le message
<p9t9tj$1i3v$ :
Non, je parle toujours du N de la discussion precedente. Revise ton
arithmetique modulaire.

Désolé, je ne comprends pas le message que tu souhaites faire passer, et
vu que tu fais tout pour ne pas l'expliquer simplement en décrivant ce
qui ne cloche, j'abandonne.

Tu as regarde ce qu'etait un generateur pseudo-aleatoire congruent ? c'est
pas comme si c'etait pas abondamment connu et documente, dans Knuth par
exemple.
Je dis depuis le debut que si tu ne sais pas de garantie sur l'algo derriere
ta fonction random() de depart, prendre un %N est une tres mauvaise idee.
Ben evidemment qu'arc4random "marche"...
Je dis depuis le debut que tu ne sais pas quel algo est utilise par random().
La qualite des generateurs pseudo-aleatoires traditionnels que ce soit
rand() ou random(), n'est aucunement garantie. Ca peut tres bien etre des
generateurs pseudo-congruents, ou une autre horreur, sur laquelle %N va
merder de facon catastrophique.

Et toi depuis le début tu m'expliques que la fonction random() est
pourrie alors que je suis intervenu dans la discussion juste pour
fournir une parade à la répartition qui était biaisée par le modulo.

Le biais de distribution est un petit souci. La faible periode
si on se base sur un modulo N et que tu as un mauvais generateur de depart
en est un bien plus gros !!!
Avatar
Olivier Miakinen
Le 02/04/2018 11:04, Marc Espie répondait à Benoît Izac :
Tu verras qu'il ne faut jamais faire % N, mais passer en flottant
et diviser par RAND_MAX, multiplier par N et arrondir...



Puis :
T'as regarde ce que c'etait qu'un generateur pseudo-aleatoire congruent ?
typiquement c'est un machin sur lequel faire %N va te donner une periode
d'au plus N.
Par exemple, tirer a pile ou face avec un pseudo-aleatoire congruent, a
coup de %2, va te donner au mieux 0 1 0 1 0 1.

Page de man de random() :
https://www.freebsd.org/cgi/man.cgi?query=random&sektion=3&apropos=0&manpath=FreeBSD+11.1-RELEASE+and+Ports
<cit.>
the low dozen bits generated by rand go through a cyclic pattern.
All the bits generated by random() are usable.
For example, `random()&01' will produce a random binary value.
</cit.>
Même si cette page précise bien que le générateur ne donne pas des
nombres complètement imprévisibles, elle dit quand même que n'importe
lesquels des bits se valent. Ce qui veut dire que faire % N n'est pas
plus mauvais que ce que tu proposes en remplacement.
[...] là on parle d'afficher une photo au hasard dans un jeu,
il faut donc relativiser.

Non. On commence avec l'affichage d'une photo au hasard d'un jeu, et puis
on passe a autre chose. Ou bien quelqu'un va tomber sur ce code et le
repomper pour autre chose.

Tiens, récemment quelqu'un m'a reproché le sophisme dit de la pente
savonneuse... on y est presque !
Je suis bien persuadé que quelqu'un comme eyaarmy, incapable d'expliquer
correctement son problème, ne fera pas dès demain un programme qui
nécessite de vrais nombres aléatoires... ou que s'il le fait, il risque
de toute manière de tomber dans d'autres pièges que le simple choix du
générateur de hasard !
On parle ici d'un probleme connu et regle depuis des annees. Je vois zero
raison de ne pas faire les choses correctement. C'est pas comme si c'etait
beaucoup plus complique. Le code necessaire existe deja et peut s'utiliser
sans souci (oui ca existe sous licence BSD, donc tu peux en faire ce que
tu veux, meme pour utilisation commerciale)

Ok. Il suffit donc de répondre à eyaarmy « la solution donnée ne donne
pas un très bon hasard mais on pense que ça devrait te suffire tant
que tu n'expliques pas mieux ton besoin ». Inutile d'en faire une guerre
de religion...
--
Olivier Miakinen
Avatar
espie
In article <pa0590$2baf$,
Olivier Miakinen <om+ wrote:
Le 02/04/2018 11:04, Marc Espie répondait à Benoît Izac :
Tu verras qu'il ne faut jamais faire % N, mais passer en flottant
et diviser par RAND_MAX, multiplier par N et arrondir...



Puis :
T'as regarde ce que c'etait qu'un generateur pseudo-aleatoire congruent ?
typiquement c'est un machin sur lequel faire %N va te donner une periode
d'au plus N.
Par exemple, tirer a pile ou face avec un pseudo-aleatoire congruent, a
coup de %2, va te donner au mieux 0 1 0 1 0 1.

Page de man de random() :
https://www.freebsd.org/cgi/man.cgi?query=random&sektion=3&apropos=0&manpath=FreeBSD+11.1-RELEASE+and+Ports
<cit.>
the low dozen bits generated by rand go through a cyclic pattern.
All the bits generated by random() are usable.
For example, `random()&01' will produce a random binary value.
</cit.>
Même si cette page précise bien que le générateur ne donne pas des
nombres complètement imprévisibles, elle dit quand même que n'importe
lesquels des bits se valent. Ce qui veut dire que faire % N n'est pas
plus mauvais que ce que tu proposes en remplacement.

Trouve-moi une spec de random() qui precise la qualite du generateur.
Je ne parle pas d'une implementation en particulier, mais bien d'une garantie
que random() va etre bien.
- random() n'est pas ISO C.
- je l'ai trouve dans POSIX (opengroup), mais zero detail... random() renvoie
un nombre pseudo-aleatoire. Rien concernant la qualite du generateur
sous-jacent.
[...] là on parle d'afficher une photo au hasard dans un jeu,
il faut donc relativiser.

Non. On commence avec l'affichage d'une photo au hasard d'un jeu, et puis
on passe a autre chose. Ou bien quelqu'un va tomber sur ce code et le
repomper pour autre chose.

Tiens, récemment quelqu'un m'a reproché le sophisme dit de la pente
savonneuse... on y est presque !
Je suis bien persuadé que quelqu'un comme eyaarmy, incapable d'expliquer
correctement son problème, ne fera pas dès demain un programme qui
nécessite de vrais nombres aléatoires... ou que s'il le fait, il risque
de toute manière de tomber dans d'autres pièges que le simple choix du
générateur de hasard !

Je pense aussi que ca vaut le coup d'avoir une discussion archivee qui
explique ce qu'il en est... meme si au final eyaarmy fait un truc simple,
il le fera sans doute en connaissance de cause. Et quelqu'un d'autre passant
par la risque de tout prendre pour argent comptant.
On parle ici d'un probleme connu et regle depuis des annees. Je vois zero
raison de ne pas faire les choses correctement. C'est pas comme si c'etait
beaucoup plus complique. Le code necessaire existe deja et peut s'utiliser
sans souci (oui ca existe sous licence BSD, donc tu peux en faire ce que
tu veux, meme pour utilisation commerciale)

Ok. Il suffit donc de répondre à eyaarmy « la solution donnée ne donne
pas un très bon hasard mais on pense que ça devrait te suffire tant
que tu n'expliques pas mieux ton besoin ». Inutile d'en faire une guerre
de religion...

C'est plus un souci didactique qu'autre chose: eviter de faire des
reponses tronquees qui pourraient propager de mauvaises idees sur le
sujet. Imagine la personne qui ne connait pas le sujet, et qui veut bien
faire.
Au moins avec cette discussion, elle sera alertee que juste prendre random()
comme argent comptant, c'est pas forcement genial SURTOUT si on fait du
code qui doit compiler un peu n'importe ou.
Avatar
Olivier Miakinen
Le 02/04/2018 15:06, Marc Espie répondait à Benoît Izac :
Je dis depuis le debut que tu ne sais pas quel algo est utilise par random().
La qualite des generateurs pseudo-aleatoires traditionnels que ce soit
rand() ou random(), n'est aucunement garantie. Ca peut tres bien etre des
generateurs pseudo-congruents, ou une autre horreur, sur laquelle %N va
merder de facon catastrophique.

D'accord, mais il suffit de RTFM pour savoir à quoi s'en tenir, et que
s'il est vrai que % N peut merder de façon catastophique avec rand()
ça ne sera pas le cas avec random().
--
Olivier Miakinen
Avatar
Olivier Miakinen
Le 03/04/2018 17:40, Marc Espie m'a répondu :
[...]

Oups, je viens de voir que tu viens juste de me répondre, mais
je n'ai plus le temps maintenant. Je répondrai plus tard.
--
Olivier Miakinen
Avatar
Olivier Miakinen
Le 03/04/2018 17:40, Marc Espie m'a répondu :
Tu verras qu'il ne faut jamais faire % N, mais passer en flottant
et diviser par RAND_MAX, multiplier par N et arrondir...



[...]

Trouve-moi une spec de random() qui precise la qualite du generateur.
Je ne parle pas d'une implementation en particulier, mais bien d'une garantie
que random() va etre bien.

Je n'en ai pas. J'ai lu le man de GNU-Linux et celui de freebsd.org.
Celui de freebsd.org, j'en ai mis un lien. Quant à celui de GNU-Linux,
il dit que chez eux le rand() est implémenté comme random(), mais que
pour avoir un code portable il faut utiliser random() plutôt que rand()
si on veut utiliser les bits de poids faible sans avoir le biais des
anciennes implémentations de rand().
Cela étant dit, ...
[...]
Je pense aussi que ca vaut le coup d'avoir une discussion archivee qui
explique ce qu'il en est... [...]

Bon, je suis d'accord. Du coup, Fermons la discussion. J'ai donné
un code qui n'était pas optimal, tout le monde a bien compris que ce
n'était pas le meilleur qui soit, mais pour que ce fil de discussion
serve à quelque chose il ne te reste plus qu'à donner un exemple de
code qui ne soit pas sujet aux critiques comme le mien.
Merci pour eyaarmy et pour tous ceux qui liront cette discussion à
l'avenir.
--
Olivier Miakinen
Avatar
espie
In article <pa0nue$2k5d$,
Olivier Miakinen <om+ wrote:
Le 03/04/2018 17:40, Marc Espie m'a répondu :
Tu verras qu'il ne faut jamais faire % N, mais passer en flottant
et diviser par RAND_MAX, multiplier par N et arrondir...



[...]

Trouve-moi une spec de random() qui precise la qualite du generateur.
Je ne parle pas d'une implementation en particulier, mais bien d'une garantie
que random() va etre bien.

Je n'en ai pas. J'ai lu le man de GNU-Linux et celui de freebsd.org.
Celui de freebsd.org, j'en ai mis un lien. Quant à celui de GNU-Linux,
il dit que chez eux le rand() est implémenté comme random(), mais que
pour avoir un code portable il faut utiliser random() plutôt que rand()
si on veut utiliser les bits de poids faible sans avoir le biais des
anciennes implémentations de rand().
Cela étant dit, ...
[...]
Je pense aussi que ca vaut le coup d'avoir une discussion archivee qui
explique ce qu'il en est... [...]

Bon, je suis d'accord. Du coup, Fermons la discussion. J'ai donné
un code qui n'était pas optimal, tout le monde a bien compris que ce
n'était pas le meilleur qui soit, mais pour que ce fil de discussion
serve à quelque chose il ne te reste plus qu'à donner un exemple de
code qui ne soit pas sujet aux critiques comme le mien.

Un petit google sur "Mersenne Twister" m'amene a:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/c-lang.html
qui m'a l'air plutot pas mal pour demarrer. Implementations variees en C,
C++, python, avec toute la documentation du monde.
Des sources pour arc4random se trouvent dans la bibliotheque C des divers
OS (BSD et autres) sous des licences idoines.
1 2 3