MantaBase wrote:
Gadget wrote:
Derek § wrote:
I used a randomizing algorithm. I based it between 0-1. I divided 1/13, 2/13, 3/13, etc. (there are 13 different possible card values; Ace(1),2,3,4,5,6,7,8,9,10,J,Q,K) to see the decimals I would get. For example, 0-0.077 represents the 2 card. Oh, hold on. I'll just show you the code in a bit, BRB.
A more common, and cleaner approach, is to use random to use the mod operator w/ random to generate values from 0 to 12. Random.getNum() * 1000 % 13 should do the trick.
wouldn't rand.num() * 168 % 13 work better? The should always give a modulus of 0 - 12. or rand.num() 1689 % 130 for better odds calculation.
also, you could have a divide by 0 exception could you not?
Manta
Recursively....
You won't have a division by zero error. 0 % 13 is the remainder when dividing 0 by 13, not 13 / 0. And we can divide zero all day long.
However, depending on the card game and how he things setup, there is a potential problem (hint: what's the difference between a permutation and combination?).
Concerning random numbers. You're correct*. If the value range is from 0 to 99 (random * 100), and we use modula 13 to segment it, we are going to have fewer opportunities for the numbers 9-12 to appear. There will be a lower segment that occurs more frequently than the upper segment. You can't really detect that something is wrong in my test code because multiplying by 1000 reduced the chance of the error occuring enough to make it undetectable by most casual methods. If I had multiplied by 20 instead of 1000, and used modula 13, it is very obvious.
*A better and shorter answer: both of our methods suck (yes, yours! see below.) and would probably cause a statistician to either chuckle or cry.
Random number generation is a very complex subject within the field of number theory. For example, one of the volumes in the art of computer programming has appx 100 pages devoted to random numbers! The bestWay() method below is based on one of the methods discussed by Knuth in the art of computer programming.
Anyways, it was late when I wrote that and betterWay() or bestWay() is how I would actually do it when thinking like a human and not a chimp.
Code:
import java.util.*;
public class RandomNumberTest {
public static int myWay() {
return (int)(Math.random() * 1000) % 13;
}
public static int myWay(int i) {
return (int)(Math.random() * i) % 13;
}
public static int yourWay() {
return (int)(Math.random() * 168) % 13;
}
public static int betterWay() { // better way, general method
return (int)(Math.random() * 13);
}
static Random rand = new Random();
public static int bestWay() { //best way in Java, this is based on a linear congruential forumula
return rand.nextInt(13);
}
public static void printArray(int[] arr) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
if (i % 5 == 0 && i != 0)
System.out.print("\n" + i + ": " + arr[i] + "\t\t");
else
System.out.print(i + ": " + arr[i] + "\t\t");
if (arr[i] < min)
min = arr[i];
if (arr[i] > max)
max = arr[i];
}
System.out.println("\nmin: " + min + "\tmax: " + max + "\tdifference: " + (max - min) + "\n");
}
public static void main(String[] args) {
System.out.println("myWay()");
int[] arr = new int[13];
for (int i = 0; i < 100000; i++)
arr[RandomNumberTest.myWay()]++;
printArray(arr);
System.out.println("yourWay()");
Arrays.fill(arr,0);
for (int i = 0; i < 100000; i++)
arr[RandomNumberTest.yourWay()]++;
printArray(arr);
System.out.println("betterWay()");
Arrays.fill(arr,0);
for (int i = 0; i < 100000; i++)
arr[RandomNumberTest.betterWay()]++;
printArray(arr);
System.out.println("bestWay()");
Arrays.fill(arr,0);
for (int i = 0; i < 100000; i++)
arr[RandomNumberTest.bestWay()]++;
printArray(arr);
System.out.println("myWay(20)");
Arrays.fill(arr,0);
for (int i = 0; i < 100000; i++)
arr[RandomNumberTest.myWay(20)]++;
printArray(arr);
System.exit(0);
}
}
Ok, this is why you run tests. The test program I wrote just counts the number of occurances of each random number then outputs them along with the min, max and difference between the min and max (a VERY casual test, but it helps spot obvious errors). Also, I overloaded myWay() with a version that takes an integer arguement to change the multiplier to any integer. You can clearly see the error when using a small arguement value like 20. Obvious as punch. In fact, if you take the average of elements 0 to 9 in myWay() and compare them to the average of elements 10 to 12, you'll see the same error pretty clearly. Takedown - 2 points Mantabase.
The method you wrote, which I call yourWay(), appears to suffer from the same error. Every time I've run the test, yourWay() not only had the largest difference between the min and max, but the min is always in the element 12. The moral of the story: It is very easy to screw up this random number stuff (even for an uber-noober Python pro-groomer!
). Escape and takedown - 3 points Gadget.
Code:
myWay()
0: 7634 1: 7767 2: 7572 3: 7790 4: 7655
5: 7673 6: 7660 7: 7734 8: 7681 9: 7836
10: 7588 11: 7603 12: 7807
min: 7572 max: 7836 difference: 264
yourWay()
0: 7792 1: 7781 2: 7673 3: 7732 4: 7795
5: 7761 6: 7830 7: 7766 8: 7701 9: 7636
10: 7736 11: 7729 12: 7068
min: 7068 max: 7830 difference: 762
betterWay()
0: 7820 1: 7560 2: 7773 3: 7583 4: 7755
5: 7785 6: 7779 7: 7633 8: 7693 9: 7592
10: 7607 11: 7613 12: 7807
min: 7560 max: 7820 difference: 260
bestWay()
0: 7707 1: 7753 2: 7719 3: 7738 4: 7655
5: 7785 6: 7636 7: 7721 8: 7717 9: 7713
10: 7689 11: 7497 12: 7670
min: 7497 max: 7785 difference: 288
myWay(20)
0: 9908 1: 9942 2: 9997 3: 10053 4: 9981
5: 9886 6: 10098 7: 5111 8: 5074 9: 4918
10: 5011 11: 5072 12: 4949
min: 4918 max: 10098 difference: 5180