001 package com.croftsoft.core.math;
002
003 import java.util.Random;
004
005 /*********************************************************************
006 * Random number generation methods.
007 *
008 * @version
009 * 2003-04-21
010 * @since
011 * 1999-01-31
012 * @author
013 * <a href="https://www.croftsoft.com/">David Wallace Croft</a>
014 *********************************************************************/
015
016 public class RandomLib
017 //////////////////////////////////////////////////////////////////////
018 //////////////////////////////////////////////////////////////////////
019 {
020
021 /** Seeded off of the current time. */
022 private static Random random = new Random ( );
023
024 //////////////////////////////////////////////////////////////////////
025 //////////////////////////////////////////////////////////////////////
026
027 /*********************************************************************
028 * Test method; prints roll(arg0, arg1, arg2).
029 *********************************************************************/
030 public static void main ( String [ ] args )
031 //////////////////////////////////////////////////////////////////////
032 {
033 long multiplier = Long.parseLong ( args [ 0 ] );
034
035 long base = Long.parseLong ( args [ 1 ] );
036
037 long offset = Long.parseLong ( args [ 2 ] );
038
039 System.out.println ( roll ( multiplier, base, offset ) );
040 }
041
042 /*********************************************************************
043 * Returns a long between 0 (inclusive) and n (exclusive).
044 *
045 * @throws IllegalArgumentException
046 *
047 * If n is negative.
048 *********************************************************************/
049 public static long nextLong ( long n )
050 //////////////////////////////////////////////////////////////////////
051 {
052 if ( n < 0 )
053 {
054 throw new IllegalArgumentException ( "negative n: " + n );
055 }
056
057 // Suppose n = 9.
058 // Numbers to be generated are 0 to 8 inclusive.
059 // Suppose Long.MAX_VALUE is 22.
060 // Factor is then 22/9 = 2.
061 // Max is then 2*9 = 18.
062 // Rolling will generate numbers between 0 and 17.
063 // Returned values will be between 0 and 8 inclusive.
064
065 long factor = Long.MAX_VALUE / n;
066
067 long max = factor * n;
068
069 long roll = -1;
070
071 while ( ( roll < 0 )
072 || ( roll >= max ) )
073 {
074 roll = random.nextLong ( );
075 }
076
077 return roll % n;
078 }
079
080 /*********************************************************************
081 * Rolls an n-sided die a specified number of times and adds an offset.
082 * For example, to roll a 6-sided die 3 times and add 4 (3d6+4),
083 * the multiplier would be 3, the base 6, and the offset 4.
084 *
085 * @param multiplier
086 * The number of times to roll the die. Must be non-negative.
087 * @param base
088 * The number of sides on the die, e.g., six.
089 * @param offset
090 * A final adjustment to add to the sum after all rolls have been
091 * made.
092 * @return
093 * Returns the sum of the rolls plus the offset.
094 * The overflow condition is not handled.
095 *********************************************************************/
096 public static long roll (
097 long multiplier,
098 long base,
099 long offset )
100 //////////////////////////////////////////////////////////////////////
101 {
102 if ( multiplier < 0 )
103 {
104 throw new IllegalArgumentException (
105 "negative multiplier: " + multiplier );
106 }
107
108 long sum = 0;
109
110 for ( long i = 0; i < multiplier; i++ )
111 {
112 sum += nextLong ( base ) + 1;
113 }
114
115 return sum + offset;
116 }
117
118 /*********************************************************************
119 * Returns a double uniformly distributed between min (inclusive) and
120 * max (exclusive).
121 *********************************************************************/
122 public static double uniform ( double min, double max )
123 //////////////////////////////////////////////////////////////////////
124 {
125 return min + ( max - min ) * random.nextDouble ( );
126 }
127
128 //////////////////////////////////////////////////////////////////////
129 //////////////////////////////////////////////////////////////////////
130 }