2. Numbers

Checking Whether a String Is a Valid Number

//----------------------------------------------------------------------------------
String s;
NumberFormat nf = NumberFormat.getInstance(locale);
Number nb;
try {
    nb = nf.parse(s);
} catch (ParseException ex) {
    // not a number
}
//----------------------------------------------------------------------------------
String s1;
try {
    int i = Integer.parseInt(s1);
} catch (NumberFormatException ex) {
    System.out.println(s1 + " is not an integer");
}

String s2;
try {
    float f = Float.parseFloat(s);
} catch (NumberFormatException ex) {
    System.out.println(s2 + " is not a float");
}
//----------------------------------------------------------------------------------
NumberFormat nf = NumberFormat.getInstance(locale);

boolean isNumeric(String string) {
    try {
       nf.parse(string);
       return true;
   } catch (ParseException ex) {
       return false;
   }
}
//----------------------------------------------------------------------------------

Comparing Floating-Point Numbers

//----------------------------------------------------------------------------------
/**
 * Returns true if given values are equal to accuracy number of decimal places
 */
boolean equal(double num1, double num2, int accuracy) {
    BigDecimal bigNum1 = new BigDecimal(num1).setScale(accuracy, BigDecimal.ROUND_DOWN);
    BigDecimal bigNum2 = new BigDecimal(num2).setScale(accuracy, BigDecimal.ROUND_DOWN);
    return (bigNum1.compareTo(bigNum2) == 0);
  }
//----------------------------------------------------------------------------------
// with a scaling factor
int wage = 536;       // $5.36/hour
int week = 40 * wage; // $214.40
System.out.println("One week's wage is: $" + (double) week/100);
//=> One week's wage is: $214.40
//----------------------------------------------------------------------------------
// with BigDecimal
BigDecimal wage = new BigDecimal("5.36"); // $5.36/hour
BigDecimal hours = new BigDecimal("40");  // 40 hours/week
BigDecimal week = wage.multiply(hours);   // $214.40
System.out.println("One week's wage is: $" + week);
//=> One week's wage is: $214.40
//----------------------------------------------------------------------------------

Rounding Floating-Point Numbers

//----------------------------------------------------------------------------------
BigDecimal rounded = unrounded.setScale(scale, roundingMode);
//----------------------------------------------------------------------------------
BigDecimal a = new BigDecimal("0.255");
BigDecimal b = a.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("Unrounded: " + a);
System.out.println("Rounded: " + b);
//=> Unrounded: 0.255
//=> Rounded: 0.26
//----------------------------------------------------------------------------------
// caution, Math.rint() rounds to the nearest integer !
double[] a = new double[] {3.3 , 3.5 , 3.7, -3.3};
System.out.println("number\tint\tfloor\tceil");
for (int i=0; i<a.length; i++)
    System.out.println(Math.rint(a[i]) + "\t" + Math.floor(a[i]) + "\t" + Math.ceil(a[i]));

//=> number  int     floor   ceil
//=> 
//=>  3.3     3.0     3.0     4.0
//=> 
//=>  3.5     3.0     3.0     4.0
//=> 
//=>  3.7     3.0     3.0     4.0
//=> 
//=> -3.3    -3.0    -4.0    -3.0
//----------------------------------------------------------------------------------

Converting Between Binary and Decimal

//----------------------------------------------------------------------------------
int i = Integer.parseInt(s, 2);
//----------------------------------------------------------------------------------
string s = Integer.toString(i, 2);
//----------------------------------------------------------------------------------
int i = Integer.parseInt("0110110", 2); // i = 54
String s = Integer.toString(54, 2);     // s = 110110
//----------------------------------------------------------------------------------

Operating on a Series of Integers

//----------------------------------------------------------------------------------
for (int i=X, i<=Y, i++) {
    i is set to every integer from X to Y, inclusive
}

for (int i=X, i<=Y, i+=7) {
    i is set to every integer from X to Y, stepsize = 7
}
//----------------------------------------------------------------------------------
System.out.print("Childhood is: ");
for (int i=5; i<=12; i++) {
    System.out.print(i + " ");
}
System.out.println();

//=> Childhood is: 5 6 7 8 9 10 11 12 
//----------------------------------------------------------------------------------

Working with Roman Numerals

//----------------------------------------------------------------------------------
// no roman module available
//----------------------------------------------------------------------------------

Generating Random Numbers

//----------------------------------------------------------------------------------
Random random = new Random();
int i = random.nextInt(Y-X+1) + X;
//----------------------------------------------------------------------------------
int i = random.nextInt(51) + 25;
System.out.println(i);
//----------------------------------------------------------------------------------
String elt = array[random.nextInt(array.length)];
//----------------------------------------------------------------------------------
StringBuffer buffer = new StringBuffer();
for (int i=0; i<8; i++)
    buffer.append((char) (random.nextInt(43) + 48));
String password = buffer.toString();
//----------------------------------------------------------------------------------

Generating Different Random Numbers

//----------------------------------------------------------------------------------
long seed;
Random random = new Random(seed);
//----------------------------------------------------------------------------------
try {
    DataInputStream input = new DataInputStream(System.in);
    Random random = new Random(input.readLong());
} catch (IOException ex) {
    System.err.println("Exception occured while initialising random seed");
}
//----------------------------------------------------------------------------------

Making Numbers Even More Random

//----------------------------------------------------------------------------------
// java.util.Random class already uses a 48-bit seed
//----------------------------------------------------------------------------------

Generating Biased Random Numbers

//----------------------------------------------------------------------------------
// use Random.nextGaussian() method
//----------------------------------------------------------------------------------
/*
 * WeightedDistribution.java
 */
package pleac.ch02.part10;

import java.util.Random;
/**
 * A weighted distribution of values
 */
public class WeightedDistribution {

    private Random random;
    private Object[] values;
    private int[] limits;
    private int total;

    /**
     * Creates a new weighted distribution with given values and given weights
     */
    public WeightedDistribution(Object[] values, int[] weights) {
        if (values.length != weights.length)
            throw new IllegalArgumentException(
                    "values and weights array size don't match");

        this.random = new Random();
        this.values = new Object[values.length];
        this.limits = new int[weights.length];
        for (int i=0; i<values.length; i++) {
            this.values[i] = values[i];
            total += weights[i];
            this.limits[i] = total;
        }
    }

    /**
     * Draws a random value
     */
    public Object draw() {
        int token = random.nextInt(total + 1);
        for (int i=0; i<limits.length; i++)
            if (token <= limits[i])
                return values[i];
        return null;
    }

}

Object values[];
int weights[];

// creates distribution
WeightedDistribution distribution = new WeightedDistribution(values, weights);
// draws a value from it
Object value = distribution.draw();
//----------------------------------------------------------------------------------
Random random = new Random();
int mean = 25;
int sdev = 2;
double salary = random.nextGaussian() * sdev + mean;
System.out.println("You have been hired at " + salary);
//----------------------------------------------------------------------------------

Doing Trigonometry in Degrees, not Radians

//----------------------------------------------------------------------------------
// use Math.toDegrees() and Math.toRadians() methods
//----------------------------------------------------------------------------------
double radians = Math.toRadians(degrees);
double degrees = Math.toDegrees(radians);
//----------------------------------------------------------------------------------
/**
 * Returns sine of an angle expressed in degrees
 */
double degreeSine(double a) {
    return Math.sin(Math.toRadians(a));
}
//----------------------------------------------------------------------------------

Calculating More Trigonometric Functions

//----------------------------------------------------------------------------------
// use Math.tan() method
//----------------------------------------------------------------------------------
double y = Math.acos(3.7);
//----------------------------------------------------------------------------------

Taking Logarithms

//----------------------------------------------------------------------------------
double log = Math.log(10000.00);
//----------------------------------------------------------------------------------
/**
 * Returns log in given base of given value
 */
double logBase(int base, double value) {
    return Math.log(value)/Math.log(base);
}
//----------------------------------------------------------------------------------
double answer = logBase(10, 10000.00);
System.out.println("log10(10000) = " + answer);
log10(10,000) = 4
//----------------------------------------------------------------------------------

Multiplying Matrices

//----------------------------------------------------------------------------------
/**
 * Compute multiplication of two given matrices
 */
int[][] multiplyMatrix(int[][] matrix1, int[][] matrix2) {

    if (matrix1 == null)
        throw new IllegalArgumentException("Null height matrix1");
    int rows1 = matrix1.length;

    if (matrix1[0] == null)
        throw new IllegalArgumentException("Null width matrix1");
    int cols1 = matrix1[0].length;

    if (matrix2 == null)
        throw new IllegalArgumentException("Null height matrix2");
    int rows2 = matrix2.length;

    if (matrix2[0] == null)
        throw new IllegalArgumentException("Null width matrix2");
    int cols2 = matrix2[0].length;

    if (cols1 != rows2) 
        throw new IllegalArgumentException("Matrices don't match: " + cols1 + " != " + rows2);

    int[][] result = new int[rows1][cols2];

    for (int i=0; i<rows1; i++) 
        for (int j=0; j<cols2; j++)
            for (int k=0; k<cols1; k++)
                result[i][j] += matrix1[i][k] * matrix2[k][j];

    return result;
}
//----------------------------------------------------------------------------------
int[][] matrix1 = new int[][] {
   {3, 2, 3},
   {5, 9, 8}
};

int[][] matrix2 = new int[][] {
   {4, 7},
   {9, 3},
   {8, 1}
};

int[][] product = multiplyMatrix(matrix1, matrix2);
//----------------------------------------------------------------------------------

Using Complex Numbers

//----------------------------------------------------------------------------------
/**
 * A basic complex number implementation
 */
public class Complex {
    
    private int real;
    private int imaginary;

    public Complex(int real, int imaginary) {
        this.real = real;
        this.imaginary = imaginary;
    }

    public int getReal() {
        return real;
    }

    public int getImaginary() {
        return imaginary;
    }

    public Complex multiply(Complex other) {
        return new Complex(
           (this.real * other.getReal()) - (this.imaginary * other.getImaginary()),
           (this.real * other.getImaginary()) + (this.imaginary * other.getReal())
       );
    }

    public String toString() {
        if (imaginary > 0)
            return real + "+" + Math.abs(imaginary) + "i";
        if (imaginary < 0)
            return real + "-" + Math.abs(imaginary) + "i";
        return real;
    }

}
//----------------------------------------------------------------------------------
Complex a = new Complex(3, 5);  // 3 + 5i
Complex b = new Complex(2, -2); // 2 - 2i
Complex c = a.multiply(b);

System.out.println("c = " + c);
//=> c = 16+4i
//----------------------------------------------------------------------------------

Converting Between Octal and Hexadecimal

//----------------------------------------------------------------------------------
int number = Integer.parseInt(hexadecimal, 16); // hexadecimal
int number = Integer.parseInt(octal, 8);        // octal
//----------------------------------------------------------------------------------
System.out.println("Gimme a number in decimal, octal, or hex: ");
try {
    BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
    String num = input.readLine().trim();
    int number;
    if (num.startsWith("0x"))
        number = Integer.parseInt(num.substring(2), 16);
        else if (num.startsWith("0"))
            number = Integer.parseInt(num.substring(1), 8);
            else
                number = Integer.parseInt(num);

    System.out.println("Decimal value: " + number);
} catch (IOException ex) {
    System.err.println("Exception occured while getting input");
} catch (NumberFormatException ex) {
    System.err.println("Exception occured while parsing input");
}
//----------------------------------------------------------------------------------
System.out.println("Enter file permission in octal: ");
try {
    BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
    String num = input.readLine().trim();
    int permission = Integer.parseInt(num, 8);

    System.out.println("Decimal value: " + permission);
} catch (IOException ex) {
    System.err.println("Exception occured while getting input");
} catch (NumberFormatException ex) {
    System.err.println("Exception occured while parsing input");
}
//----------------------------------------------------------------------------------

Putting Commas in Numbers

//----------------------------------------------------------------------------------
// using a localized number format
NumberFormat format = NumberFormat.getInstance(locale);

format.format(value);
//----------------------------------------------------------------------------------
// using a customized number format
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setGroupingSeparator(',');
DecimalFormat format = new DecimalFormat();
format.setDecimalFormatSymbols(symbols);

format.format(value);
//----------------------------------------------------------------------------------
int hits = truly_random_value(); // negative hits!
System.out.println("Your web page received " + format.format(hits) + " accesses last month.");
//=> Your web page received -1,740,525,205 accesses last month.
//----------------------------------------------------------------------------------

Printing Correct Plurals

//----------------------------------------------------------------------------------
System.out.println("It took " + time + " hour" + ((time == 1) ? "" : "s"));
System.out.println(time + " hour" + ((time == 1) ? " is" : "s are") + " enough");  
//----------------------------------------------------------------------------------
double[] limits = new double[] {1, ChoiceFormat.nextDouble(1)};
String[] names = new String[] {"century", "centuries"};
ChoiceFormat format = new ChoiceFormat(limits, names);
System.out.println("It took " + time + " " + format.format(time));
//----------------------------------------------------------------------------------
Perl5Util util = new Perl5Util();
/**
 * Compute plural of given noun
 */
String nounPlural(String noun) {
    // order really matters here!
    if (util.match("/ss$/", noun))
        return util.substitute("s/ss$/sses", noun);
    if (util.match("/([psc]h)$/", noun))
        return util.substitute("s/([psc]h)$/${1}es/", noun);
    if (util.match("/z$/", noun))
        return util.substitute("s/z$/zes/", noun);
    if (util.match("/ff$/", noun))
        return util.substitute("s/ff$/ffs/", noun);
    if (util.match("/f$/", noun))
        return util.substitute("s/f$/ves/", noun);
    if (util.match("/ey$/", noun))
        return util.substitute("s/ey$/eys/", noun);
    if (util.match("/y$/", noun))
        return util.substitute("s/y$/ies/", noun);
    if (util.match("/ix$/", noun))
        return util.substitute("s/ix$/ices/", noun);
    if (util.match("/([sx])$/", noun))
        return util.substitute("s/([sx])$/$1es/", noun);
    return util.substitute("s/$/s/", noun);
}
//----------------------------------------------------------------------------------

Program: Calculating Prime Factors

//----------------------------------------------------------------------------------
//=> # java pleac.ch02.part19.BigFact 8 9 96 2178
//=> 8: 2^3
//=> 9: 3^2
//=> 96: 2^5 3
//=> 2178: 2 3^2 11^2
//----------------------------------------------------------------------------------
//=> # java pleac.ch02.part19.BigFact 25000000000000000000000000
//=> 25000000000000000000000000: 2^24 5^26
//=> # java pleac.ch02.part19.BigFact 239322000000000000000000
//=> 239322000000000000000000: 2^19 3 5^18 39887
//----------------------------------------------------------------------------------
/*
 * BigFact.java
 */
package pleac.ch02.part19;

import java.math.BigInteger;
import java.util.*;
/**
 * Calculate prime factors
 * Usage: java pleac.ch02.part19.BigFact [-b] <number>
 */
public class BigFact {

    private static final Integer ONE = new Integer(1);

    private static TreeMap getFactors(int n) {
        int orig = n;
        TreeMap factors = new TreeMap();
        int i, sqi;
        for (i = 2, sqi = 4; sqi <= n; sqi += 2 * i++ + 1) {
            while (n % i == 0) {
                n /= i;
                Integer factor = new Integer(i);
                if (! factors.containsKey(factor))
                    factors.put(factor, ONE);
                else
                    factors.put(factor, new Integer(((Integer) factors.get(factor)).intValue() + 1));
            }
        }
        if ((n != 1) && (n != orig))
            factors.put(new Integer(n), ONE);
        return factors;
    }

    private static TreeMap getFactors(BigInteger n) {
        BigInteger orig = n;
        TreeMap factors = new TreeMap();
        BigInteger i = new BigInteger("2");
        BigInteger sqi = new BigInteger("4");
        BigInteger step = new BigInteger("2");
        while (sqi.compareTo(n) <= 0) {
            while (n.mod(i).equals(BigInteger.ZERO)) {
                n = n.divide(i);
                if (! factors.containsKey(i))
                    factors.put(i, BigInteger.ONE);
                else
                    factors.put(i, ((BigInteger) factors.get(i)).add(BigInteger.ONE));
            }
            sqi = sqi.add((i.multiply(step)).add(BigInteger.ONE));
            i = i.add(BigInteger.ONE);
        }
        if ((! n.equals(BigInteger.ONE)) && (! n.equals(orig)))
            factors.put(n, BigInteger.ONE);
        return factors;
    }

    private static void displayFactors(int n, TreeMap factors) {
        System.out.print(n + ": ");
        if (factors.isEmpty())
            System.out.println("PRIME");
        else {
            Iterator it = factors.keySet().iterator();
            while (it.hasNext()) {
                Object factor = it.next();
                Object power = factors.get(factor);
                System.out.print(factor + ((power.equals(ONE))? "": "^" + power) + " ");
            }
            System.out.println();
        }
    }

    private static void displayFactors(BigInteger n, TreeMap factors) {
        System.out.print(n + ": ");
        if (factors.isEmpty())
            System.out.println("PRIME");
        else {
            Iterator it = factors.keySet().iterator();
            while (it.hasNext()) {
                Object factor = it.next();
                Object power = factors.get(factor);
                System.out.print(factor + ((power.equals(BigInteger.ONE))? "": "^" + power) + " ");
            }
            System.out.println();
        }
    }

    public static void main(String args[]) {
        if (args.length < 1) {
            System.err.println("Usage: java pleac.ch02.part19.BigFact [-b] <number>...");
            System.exit(1);
        }

        boolean useBigInteger = false;
        int index = 0;

        if (args[0].equals("-b")) {
            useBigInteger = true;
            index = 1;
        }

        for (int i=index; i<args.length;i++) {
            if (useBigInteger) {
                BigInteger n = new BigInteger(args[i]);
                displayFactors(n, getFactors(n));
            } else {
            try {
                int n = Integer.parseInt(args[i]);
                displayFactors(n, getFactors(n));
                } catch (NumberFormatException ex) {
                    BigInteger n = new BigInteger(args[i]);
                    displayFactors(n, getFactors(n));
                }
            }
        }

    }
    
}
//----------------------------------------------------------------------------------