//
// Integer arithmetic functions (copyright 1999 Information Disciplines, Inc.)
// This pseudo-class contains various numerical functions that take
// integer parameters or return integer results. To support the widest
// range, we use long integers for all numbers, except those having a
// restricted range. To avoid anomalies, we don't use unsigned numbers.
// A few of the functions duplicate those in the java.lang.Math pseudo class.
// They are included here to provide consistency to the users
public class IntegerFunction {
// 1. Integer-valued functions of one integer:
// ------------------------------------------
public static
long abs (final long n) // Absolute value
{return n >= 0 ? n : -n;}
static // Number of digits
short ndigits(final long n, final int base)
{long nx = abs(n);
short ctr;
for (ctr = 1; nx >= base; nx /=base, ++ctr);
return ctr;}
static
short ndigits(final long n) {return ndigits(n,10);}
// 2. Integer-valued functions of two integers
// --------------------------------------------
public static
long gcd (final long m, final long n) // Greatest common divisor
{return m % n == 0 ? n : gcd(n, m%n);}
public static
long lcm (final long m, final long n) // Least common multiple
{return m * (n/gcd(m, n));}
public static
long max (final long m, final long n) // Maximum
{return m > n ? m : n;}
public static
long min (final long m, final long n) // Minimum
{return m < n ? m : n;}
// 3. String-valued functions of one or two integers:
// --------------------------------------------------
// Convert integer to string by base
// ---------------------------------
public static
String toString(final long n, final int base)
{int size = ndigits(n,base) + (n < 0 ? 1 : 0);
long nx = abs(n);
char[] result = new char[size];
if (n < 0) result[0]= '-'; // Attach prefix sign
int posn = size-1;
// Assemble characters right to left
do result[posn--] = DIGIT_TABLE.charAt((int)(nx % base));
while((nx /= base) > 0);
return new String(result);
}
static
final String DIGIT_TABLE = "0123456789ABCDEF";
public static String toString(long n) {return toString(n,10);}
// Convert integer to Roman numerals
// ---------------------------------
public static String toRoman (int arg)
{char[] unit = {'I','X','C','M'}; // Table of characters
char[] five = {'V','L','D'}; // used in Roman numerals
char[] result = new char[16]; // Accumulator for results
short resultPosn = 15; // Right-to-left index
short digit; // Current digit
boolean five_sw; // Cur. digit needs initial five
int n = Math.abs(arg);
short posn;
if (n >= 4000) // Test for within acceptable range
return toString(n,10); // No -- just return Arabic numerals
for (posn = 0; n > 0; posn++, n /= 10)
{digit = (short)(n % 10);
if (digit == 9) {result[resultPosn--] = unit[posn+1]; digit = 1;}
if (digit == 4) {result[resultPosn--] = five[posn]; digit = 1;}
five_sw = (digit >= 5);
digit %= 5; // Number of units in this position
while (digit-- > 0) result[resultPosn--] = unit[posn];
if (five_sw) result[resultPosn--] = five[posn];
}
return new String(result).substring(resultPosn+1);
}
// Integer to English
// ------------------
// 1. Internal function to convert 3-digit portion:
// -------------------------------------------------
private static String toEng999 (int k)
{final String[] units = {"" ,"one" ,"two" ,"three" ,"four",
"five","six" ,"seven" ,"eight" ,"nine",
"ten","eleven" ,"twelve" ,"thirteen","fourteen",
"fifteen","sixteen","seventeen","eighteen","nineteen"};
final String[] tens = {"" , "" ,"twenty" ,"thirty" ,"forty" ,
"fifty","sixty" ,"seventy" ,"eighty" ,"ninety"};
int u = k % 10; // Separate the
int c = k / 100; // values of the
int tu= k % 100; // three digits
int t = (tu-u) / 10;
String result = (c == 0) ? "" // Insert hundreds portion
: units[c] + " hundred"
+ (tu > 0 ? " " : "");
return result += (tu < 20) ? units[tu] // Insert tens and units portion
: tens [t]
+ ( u > 0 ? "-" : "")
+ units[u];
}
// 2. Function called by the user
// -------------------------------
static public String toEnglish (long arg)
{final String[] grpName ={""," thousand"," million"," billion",
" trillion"," quadrillion"," quintillion"};
String result = "";
long n = abs(arg);
for (int group_ctr=0; n>0; ++group_ctr) // Process each group of 3-digits
{int group = (int) (n % 1000);
n /= 1000; // right to left
if (group != 0) // For each non-zero group
result = toEng999(group) // Insert group value
+ grpName[group_ctr] // and group denomination
+(result.length() > 0 ? ", " : "")// Insert separating comma
+ result; // Append rightmost portion
}
return arg != 0 ? result : "zero";
}
// 4. Other functions
// -------------------
// Decompose integer into prime factors
// ------------------------------------
// Upon return result[0] contains the number of factors (0 if N is 0), and
// result[1] . . . result[result[0]] contain the factors in ascending order.
public static long[] primeFactors(long N)
{long [] fctr = new long[64]; // Result array
long n = Math.abs(N); // Guard against negative
short fctrIndex = 0;
if (n > 0) { // Guard against zero
// First do special cases 2 and 3
while (n % 2 == 0) {fctr[++fctrIndex] = 2; n /= 2;}
while (n % 3 == 0) {fctr[++fctrIndex] = 3; n /= 3;}
// Then every 6n-1 and 6n+1 until the divisor exceeds the square root
// of the current quotient. NOTE: Some trial divisors will be
// non-primes, e.g. 25, 35, 49, 55. They have no effect, however,
// since their prime factors will already have been tried.
for (int k = 5; k*k <= n; k += 6)
for (int dvsr = k; dvsr <= k+2; dvsr+=2)
{ while (n % dvsr == 0)
{fctr[++fctrIndex] = dvsr; n /= dvsr;}
}
if (n > 1) fctr[++fctrIndex] = n; // Store final factor, if any
}
fctr[0] = fctrIndex; // Store number of factors
return fctr;
}
// Integer power of a real number (recursive implementation)
// ------------------------------
public static double power(double x, int n) // (Overflow is possible)
{return n < 0 ? 1 / power(x,-n) // Negative power
: n == 0 ? 1 // Base
: n == 1 ? x // cases
: n%2 == 0 ? (x = power(x, n/2)) * x // Even power
: x * power(x, n-1);} // Odd power
}
//