[SQL Server] Problème avec RAND()

Problème avec RAND() [SQL Server] - SQL/NoSQL - Programmation

Marsh Posté le 03-06-2005 à 21:17:38    

Décidément...
 
On n'utilise pas souvent les SGBD pour générer des nombres aléatoires, et visiblement, ça manque !
 
Je suis en train d'écrire une procédure stockée qui doit remplir automatiquement une table avec des valeurs aléatoires en fonction des paramètres passés.
 
Et... J'ai un problème : malgré un SEED qui diffère d'un appel à l'autre, j'ai le même jeu de données qui se produit d'un appel à l'autre !
 
Voici le code :
 

Code :
  1. -- Terrain creation
  2. CREATE PROCEDURE CreateTerrain
  3. (
  4. @idSolarSystem as numeric,
  5. @idPlanet as numeric,
  6. @xTerrain as tinyint,
  7. @yTerrain as tinyint
  8. )
  9. AS
  10. declare @ground0 as tinyint
  11. declare @ground1 as tinyint
  12. declare @ground2 as tinyint
  13. declare @ground3 as tinyint
  14. declare @ground4 as tinyint
  15. declare @ground5 as tinyint
  16. declare @ground6 as tinyint
  17. declare @ground7 as tinyint
  18. declare @ground8 as tinyint
  19. declare @ground9 as int
  20. declare @ratioOK as bit
  21. declare @cpt as numeric
  22. BEGIN
  23. SET @ratioOK = 0
  24. SET @cpt = 0
  25. WHILE @ratioOK = 0
  26. BEGIN
  27.  SET @cpt = @cpt + 1
  28.  SELECT @ground0 = 1 + CAST((RAND(@idSolarSystem + @idPlanet + @xTerrain + @yTerrain + @cpt) * 19) as tinyint)
  29.  SELECT @ground1 = CAST((RAND(@idSolarSystem + @idPlanet + @xTerrain + @yTerrain + @cpt * 2) * 20) as tinyint)
  30.  SELECT @ground2 = CAST((RAND(@idSolarSystem + @idPlanet + @xTerrain + @yTerrain + @cpt * 3) * 20) as tinyint)
  31.  SELECT @ground3 = CAST((RAND(@idSolarSystem + @idPlanet + @xTerrain + @yTerrain + @cpt * 4) * 20) as tinyint)
  32.  SELECT @ground4 = CAST((RAND(@idSolarSystem + @idPlanet + @xTerrain + @yTerrain + @cpt * 5) * 20) as tinyint)
  33.  SELECT @ground5 = CAST((RAND(@idSolarSystem + @idPlanet + @xTerrain + @yTerrain + @cpt * 6) * 20) as tinyint)
  34.  SELECT @ground6 = CAST((RAND(@idSolarSystem + @idPlanet + @xTerrain + @yTerrain + @cpt * 7) * 20) as tinyint)
  35.  SELECT @ground7 = CAST((RAND(@idSolarSystem + @idPlanet + @xTerrain + @yTerrain + @cpt * 8) * 20) as tinyint)
  36.  SELECT @ground8 = CAST((RAND(@idSolarSystem + @idPlanet + @xTerrain + @yTerrain + @cpt * 9) * 20) as tinyint)
  37.  SELECT @ground9 = 100 - Cast(@ground0 + @ground1 + @ground2 + @ground3 + @ground4 + @ground5 + @ground6 + @ground7 + @ground8 as int)
  38.  IF @ground9 > 0
  39.  BEGIN
  40.   SET @ratioOK = 1
  41.  END
  42. END
  43. INSERT INTO Terrain
  44.  (idSolarSystem, idPlanet, xTerrain, yTerrain, ground0, ground1, ground2, ground3, ground4, ground5, ground6, ground7, ground8, ground9)
  45. VALUES
  46.  (@idSolarSystem, @idPlanet, @xTerrain, @yTerrain, @ground0, @ground1, @ground2, @ground3, @ground4, @ground5, @ground6, @ground7, @ground8, Cast(@ground9 as tinyint))
  47. END
  48. GO


 
En sortie, dans la table "Terrain", j'ai ce genre de choses...
 

Code :
  1. idSolarSystem        idPlanet             xTerrain yTerrain ground0 ground1 ground2 ground3 ground4 ground5 ground6 ground7 ground8 ground9 owner                settleDate                                           
  2. -------------------- -------------------- -------- -------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- -------------------- ------------------------------------------------------
  3. 6                    1                    1        1        15      16      17      18      19      0       0       1       2       12      NULL                 NULL
  4. 6                    1                    1        2        15      16      17      18      19      0       0       1       2       12      NULL                 NULL
  5. 6                    1                    1        3        15      16      17      18      19      0       0       1       2       12      NULL                 NULL
  6. 6                    1                    1        4        15      16      17      18      19      0       0       1       2       12      NULL                 NULL
  7. 6                    1                    1        5        15      16      17      18      19      0       0       1       2       12      NULL                 NULL
  8. 6                    1                    1        6        15      16      17      18      19      0       0       1       2       12      NULL                 NULL
  9. 6                    1                    1        7        15      16      17      18      19      0       0       1       2       12      NULL                 NULL
  10. 6                    1                    1        8        15      16      17      18      19      0       0       1       2       12      NULL                 NULL
  11. 6                    1                    1        9        15      16      17      18      19      0       0       1       2       12      NULL                 NULL
  12. 6                    1                    1        10       15      16      17      18      19      0       0       1       2       12      NULL                 NULL


 
Comme vous le voyez, les champs "aléatoires" ne changent jamais :/


Message édité par Arjuna le 03-06-2005 à 21:17:59
Reply

Marsh Posté le 03-06-2005 à 21:17:38   

Reply

Marsh Posté le 03-06-2005 à 21:20:20    

Je devrais pourtant me retrouver dans la même situation que cet exemple... (doc de SQL Server) :sweat:
 

Code :
  1. Exemple
  2. Cet exemple produit quatre nombres aléatoires différents avec la fonction RAND.
  3. DECLARE @counter smallint
  4. SET @counter = 1
  5. WHILE @counter < 5
  6.    BEGIN
  7.       SELECT RAND(@counter) Random_Number
  8.       SET NOCOUNT ON
  9.       SET @counter = @counter + 1
  10.       SET NOCOUNT OFF
  11.    END
  12. GO

Reply

Marsh Posté le 03-06-2005 à 21:35:28    

:ouch:
 
Comprend rien...
 
Je viens de refaire un test et... je commence à avoir des données différentes à partir d'un seed >= 2^15 !
 

Code :
  1. SET nocount ON
  2. drop procedure test2
  3. go
  4. drop procedure test1
  5. go
  6. create procedure test2
  7. (
  8. @cpt as numeric
  9. )
  10. as
  11. begin
  12. select Cast(rand(@cpt) * 20 as tinyint)
  13. end
  14. go
  15. create procedure test1
  16. as
  17. declare @cpt as numeric
  18. declare @tmp as numeric
  19. begin
  20. set @cpt = 0
  21. while @cpt < 20
  22. begin
  23.  set @tmp = power(2, @cpt)
  24.  exec test2 @tmp
  25.  set @cpt = @cpt + 1
  26. end
  27. end
  28. go
  29. print 'mon test'
  30. exec test1


 
Résultat :
 

Code :
  1. mon test
  2.    
  3. ----
  4. 14
  5. 14
  6. 14
  7. 14
  8. 14
  9. 14
  10. 14
  11. 14
  12. 14
  13. 14
  14. 14
  15. 15
  16. 15
  17. 17
  18. 0
  19. 6
  20. 18
  21. 3
  22. 11
  23. 9


Message édité par Arjuna le 03-06-2005 à 21:35:49
Reply

Marsh Posté le 03-06-2005 à 21:38:26    

C'est quoi, ta DB, là ? Tu fais un jeu ?

Reply

Marsh Posté le 03-06-2005 à 21:39:08    

T'ain... Et en plus, faut que les valeurs soient à la fois grandes et très différentes pour que ça marche...
 
2^15 retourne comme 2^15 + 1 ou 2^15 + 2 ... + 100 :fou:

Reply

Marsh Posté le 03-06-2005 à 21:40:50    

Yep, je fais un jeu genre Civilization mélangé avec du Colonization, le tout à la sauce Outpost, sans oublier que c'est un jeu en ligne (site web) à la kochonland.
 
Ben ouais, mon précédent, BuzzLand, il était un peu limité, et j'avais pas d'idée pour réellement le faire décoller. Là au moins, en me basant sur ces jeux, je suis certain d'avoir des idées, et trouver des fidèles :D

Reply

Marsh Posté le 03-06-2005 à 22:02:28    

Hé bé...
 
Bon, ça ressemble un peu à de l'aléatoire, à condition de pas avoir les lignes sous les yeux... :sweat:
 

Code :
  1. -- Terrain creation
  2. CREATE PROCEDURE CreateTerrain
  3. (
  4. @idSolarSystem as numeric,
  5. @idPlanet as numeric,
  6. @xTerrain as tinyint,
  7. @yTerrain as tinyint
  8. )
  9. AS
  10. declare @ground0 as tinyint
  11. declare @ground1 as tinyint
  12. declare @ground2 as tinyint
  13. declare @ground3 as tinyint
  14. declare @ground4 as tinyint
  15. declare @ground5 as tinyint
  16. declare @ground6 as tinyint
  17. declare @ground7 as tinyint
  18. declare @ground8 as tinyint
  19. declare @ground9 as int
  20. declare @ratioOK as bit
  21. declare @cpt as numeric
  22. BEGIN
  23. SET @ratioOK = 0
  24. SET @cpt = 0
  25. WHILE @ratioOK = 0
  26. BEGIN
  27.  SET @cpt = @cpt + 1
  28.  SELECT @ground0 = 1 + CAST((RAND(((@cpt * pi()) + @idSolarSystem + @xTerrain + @yTerrain + 1) * 10000) * 19) as tinyint)
  29.  SELECT @ground1 = CAST((RAND(power(@cpt, @ground0) + (@idSolarSystem + @xTerrain + @yTerrain) * 10000) * 20) as tinyint)
  30.  SELECT @ground2 = CAST((RAND(power(@cpt, @ground1) + (@idSolarSystem + @xTerrain + @yTerrain) * 10000) * 20) as tinyint)
  31.  SELECT @ground3 = CAST((RAND(power(@cpt, @ground2) + (@idSolarSystem + @xTerrain + @yTerrain) * 10000) * 20) as tinyint)
  32.  SELECT @ground4 = CAST((RAND(power(@cpt, @ground3) + (@idSolarSystem + @xTerrain + @yTerrain) * 10000) * 20) as tinyint)
  33.  SELECT @ground5 = CAST((RAND(power(@cpt, @ground4) + (@idSolarSystem + @xTerrain + @yTerrain) * 10000) * 20) as tinyint)
  34.  SELECT @ground6 = CAST((RAND(power(@cpt, @ground5) + (@idSolarSystem + @xTerrain + @yTerrain) * 10000) * 20) as tinyint)
  35.  SELECT @ground7 = CAST((RAND(power(@cpt, @ground6) + (@idSolarSystem + @xTerrain + @yTerrain) * 10000) * 20) as tinyint)
  36.  SELECT @ground8 = CAST((RAND(power(@cpt, @ground7) + (@idSolarSystem + @xTerrain + @yTerrain) * 10000) * 20) as tinyint)
  37.  SELECT @ground9 = 100 - Cast(@ground0 + @ground1 + @ground2 + @ground3 + @ground4 + @ground5 + @ground6 + @ground7 + @ground8 as int)
  38.  IF @ground9 > 0
  39.  BEGIN
  40.   SET @ratioOK = 1
  41.  END
  42. END
  43. INSERT INTO TERRAIN
  44.  (idSolarSystem, idPlanet, xTerrain, yTerrain, ground0, ground1, ground2, ground3, ground4, ground5, ground6, ground7, ground8, ground9)
  45. VALUES
  46.  (@idSolarSystem, @idPlanet, @xTerrain, @yTerrain, @ground0, @ground1, @ground2, @ground3, @ground4, @ground5, @ground6, @ground7, @ground8, cast(@ground9 as tinyint))
  47. END
  48. GO


 
Même pas peur :D

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed