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         }