Monday, October 30, 2006

MathUtil

Useful Math utilities

/*
 * net/balusc/util/MathUtil.java
 * 
 * Copyright (C) 2007 BalusC
 * 
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this program; if
 * not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

package net.balusc.util;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

/**
 * Useful Math utilities.
 * 
 * @author BalusC
 * @link http://balusc.blogspot.com/2006/10/mathutil.html
 */
public final class MathUtil {

    // Init ---------------------------------------------------------------------------------------

    private static final Random RANDOM = new Random();

    private MathUtil() {
        // Utility class, hide the constructor.
    }

    // Actions ------------------------------------------------------------------------------------

    /**
     * Generates unique ID based on timestamp, thread ID, random seed and random double. Each part
     * is converted to hexadecimal, padded left with zeros to a length of 8 chars and then
     * concatentated to each other.
     * @return Unique 32-char hexadecimal string.
     */
    public static synchronized String uniqueID() {
        final String pad = "0";
        final int padLength = 8;
        final int padDirection = StringUtil.PAD_LEFT;

        String timestamp = Integer.toHexString((int) System.currentTimeMillis());
        String threadHashCode = Integer.toHexString(Thread.currentThread().hashCode());
        String randomInt = Integer.toHexString(RANDOM.nextInt());
        String mathRandom = Integer.toHexString((int) (Math.random() * Integer.MAX_VALUE));

        // You may remove this try block if you want to increase performance by 1ms.
        // But the generated ID might not be fully 100% guaranteed to be unique.
        // If you want to keep this block, then you can "almost" safely remove the
        // randomInt and mathRandom parts of the UniqueID.
        try {
            Thread.sleep(1); // System.currentTimeMillis()++
        } catch (InterruptedException e) {
            // Do nothing. This exception shouldn't occur however since we are
            // in a synchronized block. I haven't seen it been thrown earlier.
        }

        return StringUtil.pad(timestamp, pad, padLength, padDirection)
            + StringUtil.pad(threadHashCode, pad, padLength, padDirection)
            + StringUtil.pad(randomInt, pad, padLength, padDirection)
            + StringUtil.pad(mathRandom, pad, padLength, padDirection);
    }

    /**
     * Generate MD5 hash for the given String. MD5 is kind of an one-way encryption. Very useful for
     * hashing passwords before saving in database.
     * @param string The String to generate the MD5 hash for.
     * @return The 32-char hexadecimal MD5 hash of the given String, if necessary padded left with
     * one zero.
     */
    public static String hashMD5(String string) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            String hash = new BigInteger(md5.digest(string.getBytes("UTF-8"))).abs().toString(16);
            return StringUtil.pad(hash, "0", 32, StringUtil.PAD_LEFT);
        } catch (NoSuchAlgorithmException e) {
            // Unusual exception. "MD5" is just hardcoded and supported.
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            // Unusual exception. "UTF-8" is just hardcoded and supported.
            throw new RuntimeException(e);
        }
    }

    /**
     * Factorial calculator with nearly unlimited outcome.
     * @param n The number to calculate factorial for.
     * @return The factorial of the given number.
     */
    public static BigInteger factorial(BigInteger n) {
        BigInteger factorial = BigInteger.ONE;

        while (n.compareTo(BigInteger.ONE) == 1) {
            factorial = factorial.multiply(n);
            n = n.subtract(BigInteger.ONE);
        }

        return factorial;
    }

    /**
     * Generate random number < Short.MAX_VALUE.
     * @return Random number < Short.MAX_VALUE.
     */
    public static Number randomNumber() {
        return new Integer((int) (Math.random() * Short.MAX_VALUE));
    }

    /**
     * Generate random string matching [0-9a-z]{1,6}.
     * @return Random string matching [0-9a-z]{1,6}.
     */
    public static String randomString() {
        return Integer.toString((int) (Math.random() * Integer.MAX_VALUE) & Integer.MAX_VALUE, 36);
    }

}

You can find the required StringUtil utility class here.

Copyright - GNU General Public License

(C) October 2006, BalusC

0 comments: