Numbers will be equals if enough decimals are equals, without thinking about approximations. : Number « Data Type « Java






Numbers will be equals if enough decimals are equals, without thinking about approximations.

       
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/*
 * Copyright 2007-2011 Nicolas Zozol
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
//package com.robustaweb.library.commons.util;

/**
 * This class is designed to simplify Numbers representation in HTML views. <p>Be aware that it's not time efficiency, not designed for complex Math</p>.
 * @author Nicolas Zozol for Robusta Web ToolKit & http://www.edupassion.com - nzozol@robustaweb.com
 */
public class MathUtils {

    /**
     *  Numbers will be equals if enough decimals are equals, without thinking about approximations. This is absolutely not a pure mathematic Equality.
     * <p>
     * approximativelyEquals(1.2352, 1.2357, 3) returns true because there is no rounding at the 3th decimal
     * </p>
     *
     * @param n1 first numbre
     * @param n2 second number
     * @param decimalPrecision
     * @return true if n1 is approximatively equal to n2
     */
    public static boolean approximativelyEquals(Number n1, Number n2, int decimalPrecision) {


        if (n1.toString().equals(n2.toString())) {
            return true;
        }

        String s1 = n1.toString();
        String s2 = n2.toString();

        s1 = StringUtils.removeTrailingCharacters(s1, '0');
        s2 = StringUtils.removeTrailingCharacters(s2, '0');



        if (!s1.contains(".") && !s2.contains(".")) {
            return s1.equals(s2);
        }

        int seriousNumber;
        if (s1.contains(".")) {
            seriousNumber = s1.indexOf('.');
        } else {//s2.contains(".")
            seriousNumber = s2.indexOf('.');
        }

        /* checking before */
        if (s1.substring(0, seriousNumber).equals(s2.substring(0, seriousNumber))) {

            s1 = s1.substring(seriousNumber);
            s1 = StringUtils.removeCharacter(s1, '.');
            s2 = s2.substring(seriousNumber);
            s2 = StringUtils.removeCharacter(s2, '.');

            /* truncation */
            String t1 = StringUtils.truncate(s1, decimalPrecision);
            String t2 = StringUtils.truncate(s2, decimalPrecision);
            t1 = StringUtils.removeTrailingCharacters(t1, '0');
            t2 = StringUtils.removeTrailingCharacters(t2, '0');
            return t1.equals(t2);


        } else {
            return false;
        }
    }

    /**
     * <p>
     * Returns a visual approximation of a number, keeping only a specified decimals. <br/>
     * For exemple : <br/>
     *    &nbsp; approximate(12.2578887 , 2) will return 12.25 <br/>
     *    &nbsp; approximate(12.25 , 0) will return 12 <br/>
     *    &nbsp; approximate(12.00 , 3) will return 12 <br/>
     *    &nbsp; approximate(19.5 , 0) will return 20 <br/>
     *</p>
     * <p>The last exemple emphasis the fact that it's made for showing convenient numbers for no mathematical public. If the number was</p>
     * <p>Note that Math.round(19.5) returns 20, not 19. This function will act the same way.</p>
     * @param n
     * @param precision
     * @return
     */
    public static String approximate(Number n, int precision) {


        if (n instanceof Integer) {
            return n.toString();
        }



        String s = n.toString();

        if (!s.contains(".")) {
            return s;
        }

        String serious = s.substring(0, s.indexOf('.'));

        s = s.substring(s.indexOf('.') + 1);
        s = StringUtils.removeTrailingCharacters(s, '0');

        if (s.length() == 0) {
            return serious;
        }


        // We'll comments results based on approximate(12.63645, 3) and approximate(12.63545, 0)
        String decimals = "";

        if (s.length() > precision) {


            decimals = StringUtils.truncate(s, precision + 1);
            //decimal is now "636" or "6"

            Float after = new Float(decimals);
            //after is 636 or 6, as Float objects
            after = after / 10;
            //after is 63.6 or .6, as Float objects
            Integer round = Math.round(after);
            //round is 64 or 1
            decimals = round.toString();
            decimals = StringUtils.removeTrailingCharacters(decimals, '0');

        } else {

            decimals = StringUtils.truncate(s, precision);
            decimals = StringUtils.removeTrailingCharacters(decimals, '0');

        }



        if (decimals.length() > 0 && precision > 0) {
            return serious + "." + decimals;
        } else {
            //if we must round the serious string
            if (decimals.length() > 0 && precision == 0) {
                assert decimals.length() == 1 : "problem here !";
                if (decimals.length() != 1) {
                    throw new IllegalStateException("Error in the algorithm for MathUtilisties.approximate(" + n + ", " + precision + ")");
                }
                Integer finalValue = new Integer(decimals);
                if (finalValue > 0) {
                    Integer si = new Integer(serious);
                    si += 1;
                    return si.toString();
                } else {
                    return serious;
                }
            } else {
                return serious;
            }
        }
    }

    /**
     * Convert a String in Double, Float, Integer, Long, Short or Byte, depending on the T exemple
     * For exemple convert("2", 0f) will return 2.0 as a float
     * @param <T> type returned
     * @param str String to convert
     * @param exemple exemple of the type
     * @return a number representation of the String
     * @throws IllegalArgumentException if the T type is not Double, Float, Integer, Long, Short or Byte
     * @throws NumberFormatException if the conversion fails
     */
    public static <T extends Number> T convert(String str, T exemple) throws NumberFormatException, IllegalArgumentException{

        T result = null;
        if (exemple instanceof Double) {
            result = (T) new Double(str);
        } else if (exemple instanceof Float) {
            result = (T) new Float(str);
        } else if (exemple instanceof Integer) {
            result = (T) new Integer(str);
        } else if (exemple instanceof Long) {
            result = (T) new Long(str);
        } else if (exemple instanceof Short) {
            result = (T) new Short(str);
        } else if (exemple instanceof Byte) {
            result = (T) new Byte(str);
        }else{
            throw new IllegalArgumentException("Conversion is not possible with class "+exemple.getClass()
                    +"; only allowing Double, Float, integer, Long, Short & Byte");
        }

        return result;

    }
  
}

/**
 * This class gives a few function to waork on Strings.
 * <p>Most importants are probably <ul>
 * <li>{@link StringUtils#validateEmail(String) validateEmail()}
 * <li>{@link StringUtils#replaceAll(String, String, String) replaceAll()}
 * <li> {@link StringUtils#removeCharacters(String, String) removeCharacters()}
 * </ul>
 * </p>
 * @author Nicolas Zozol for Robusta Web ToolKit & http://www.edupassion.com - nzozol@robustaweb.com
 * TODO : verify this class is GWT compatible
 */
 class StringUtils {

    /**
     * This function test if an email is valid. It's not the best validation of the world : all good emails will pass,
     * but some wrong emails (even if it's very unlikely) may also pass.
     * <p> This function is based on the Javascript pattern /^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+\.([a-zA-Z])+([a-zA-Z])+/
     * </p>
     * <p>Check <a href="http://www.ietf.org/rfc/rfc2822.txt">IETF</a> for more informations.</p>
     * @param email email to be tested
     * @return true if email is an email pattern, false if not
     * @throws  IllegalArgumentException if the email is null
     */
    public static boolean validateEmail(String email) {

        if (email == null) {
            throw new IllegalArgumentException("The email is null");
        }
        if (email.equals("")) {
            return false;
        }
        String worker = new String(email);
        worker = worker.trim();

        return worker.matches("^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+\\.([a-zA-Z])+([a-zA-Z])+");
        /*
        //Set the email pattern string
        //Pattern p = Pattern.compile(".+@.+\\.[a-z]+");
        Pattern p = Pattern.compile("^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+\\.([a-zA-Z])+([a-zA-Z])+");
        //Match the given string with the pattern
        Matcher m = p.matcher(worker);

        return m.matches();*/
    }

    /**
     * Returns true if the String could be a md5
     * @param md5String String to test : could it be a MD5, or there is no way ?
     * @return true if the String could be a md5
     * @throws IllegalArgumentException if the md5String is null
     */
    public static boolean validateMD5(String md5String) {

        if (md5String == null) {
            throw new IllegalArgumentException("md5String is null");
        }

        return md5String.length() == 32 && md5String.matches("([a-z0-9])+");

    }

    /**
     * <p>removes a character in the String </p>
     *
     * <p>
     * String boss="Bruce Springsteen";<br/>
     * String result = StringUtils.removeCharacter(boss, 'e') returns "Bruc Springstn".<br/>
     * But the original String boss is not modified.
     * </p>
     * @param originalString
     * @param c
     * @return
     */
    public static String removeCharacter(String string, char c) {

        String work = new String(string);

        String s = "" + c;
        work = work.replace(s, "");
        return work;
    }

    /**
     * <p>Removes in the string every characters inside charactersToRemove.<br/>
     * For exemple removeCharacters("Napoleon","nou") returns Naple because it will remove one 'n', two 'o' and zero 'u' <br/>
     * Like for removeCharacter(String string, char c), the original String is not modified.</p>
     * <p>It's a recursive function, not the fastest you may have.</p>
     * 
     * @param originalString Original string
     * @param charactersToRemove characters that will be removed form the Original String
     * @return a new string without the specified characters
     * @throws IllegalArgumentException if original or charactersToRemove is null
     */
    public static String removeCharacters(String original, String charactersToRemove) {

        if (original == null) {
            throw new IllegalArgumentException("Your original parameter is null");
        }
        if (charactersToRemove == null) {
            throw new IllegalArgumentException("charactersToRemove parameter si null");
        }

        String work = new String(original);

        char c;
        for (int i = 0; i < charactersToRemove.length(); i++) {
            c = charactersToRemove.charAt(i);
            work = removeCharacter(work, c);
        }
        return work;

    }

    /**
     * Will remove all characters from the end. <br/>
     * <p>
     * removeStartingCharacters(iiiiMalagi, 'i') returns Malagi
     * </p>
     * If the string is empty, it returns also an empty string.
     * If the string is null, it will throw a IllegalArgumentException
     * @param originalString Original parameter
     * @param character
     * @throws IllegalArgumentException : if the string is null
     * @return Removes all the specified character found at the beginning of the string
     */
    public static String removeStartingCharacters(String originalString, char character) {

        if (originalString == null) {
            throw new IllegalArgumentException("original String is null");
        }

        if (originalString.length() == 0) {
            return originalString;
        }

        String result = new String(originalString);


        while (result.indexOf(character) == 0) {
            result = removeFirstCharacter(result);
            if (result.length() == 0) {
                return "";
            }
        }

        return result;
    }

    /**
     * Will remove all characters from the end. <br/>
     * <p>
     * removeTrailingCharacters(Malagaaaa, 'a') returns Malag
     * </p>
     * If the string is empty, it returns also an empty string.
     * If the string is null, it will throw a IllegalArgumentException
     * @param originalString Original parameter
     * @param character
     * @throws IllegalArgumentException : if the string is null
     * @return Removes all the specified character found at the end of the string
     */
    public static String removeTrailingCharacters(String originalString, char character) {

        if (originalString == null) {
            throw new IllegalArgumentException("original String is null");
        }

        if (originalString.length() == 0) {
            return originalString;
        }

        String result = new String(originalString);


        while (result.lastIndexOf(character) == result.length() - 1) {
            result = removeLastCharacter(result);
            if (result.length() == 0) {
                return "";
            }
        }

        return result;
    }


    /**
     * <p>Simply removes the last character</p>
     * @param originalString
     * @return a new String without the
     * @throws IllegalArgumentException if the string is null
     */
    public static String removeFirstCharacter(String originalString) {

        if (originalString == null) {
            throw new IllegalArgumentException("string is null");
        }

        if (originalString.length() <= 1) {
            return "";
        }
        return originalString.substring(1);


    }

    /**
     * <p>Simply removes the last character</p>
     * @param originalString
     * @return a new String without the
     * @throws IllegalArgumentException if the string is null
     */
    public static String removeLastCharacter(String originalString) {

        if (originalString == null) {
            throw new IllegalArgumentException("string is null");
        }

        if (originalString.length() <= 1) {
            return "";
        }
        return originalString.substring(0, originalString.length() - 1);


    }

    /**
     * <p>This is a simpler alternative to original String.replaceAll function that uses complex Regexp.
     * Here, you modify a String by changing the <strong>characters sequence</strong> sequenceToReplace by the replacement string.</p>
     *
     * <p>
     * Exemple :<br/>
     *  &nbsp;<code>String original = "//cooluri//living.js///";</code><br/>
     * Then <br/>
     *  &nbsp;<code>StringUtils.replaceAll(original,"//", "-");</code><br/>
     * will return :<br/>
     * -cooluri-living.js-/
     * </p>
     * <p>Note that the '///' is always seen as ('//'+'/') and <strong>never</strong> as ('/'+'//'). This function is <strong>sequential</strong>, and will not always work like regular expressions.</p>     
     * @param originalString The original string
     * @param sequenceToReplace The characters sequence to replace
     * @param replacement
     * @return
     * @throws IllegalArgumentExceptionif a param is null
     */
    public static String replaceSequence(String originalString, String sequenceToReplace, String replacement) {


        if (originalString == null) {
            throw new IllegalArgumentException("originalString is null");
        }
        if (sequenceToReplace == null) {
            throw new IllegalArgumentException("charsToReplace is null");
        }
        if (replacement == null) {
            throw new IllegalArgumentException("replacement is null");
        }
        if (sequenceToReplace.equals(replacement)){
            return originalString;
        }
        
        String newString = new String(originalString);
        if (originalString == null || originalString.length() == 0) {
            return originalString;
        }
        if (sequenceToReplace == null || sequenceToReplace.length() == 0) {
            return originalString;
        }
        int indexPiece = originalString.indexOf(sequenceToReplace);
        while (indexPiece != -1) {
            newString = newString.substring(0, indexPiece) + replacement + newString.substring(indexPiece + sequenceToReplace.length());
            indexPiece = newString.indexOf(sequenceToReplace);
        }

        return newString;
    }


    /**
     * Replace any character defined in anyCharacter by a replacement sequence
     * Ex :
     * <pre>
     * replaceAny("john jack jim", "ji", "t") => "tohn tack ttm"
     * </pre>
     * @param originalString
     * @param anyCharacter
     * @param replacement
     * @return
     */
    public static String replaceAny(String originalString, String anyCharacter, String replacement){

        String worker = originalString;
        for (Character c : anyCharacter.toCharArray()){
            String pattern = ""+c;
            worker = worker.replaceAll(pattern, replacement);
        }
        return worker;
    }

    /**
     * <p>Keeps the 'number' first characters, and might be useful to keep your user's privacy :<br/>
     * &nbsp;<code>truncate("Hernandez", 3)</code><br/>
     * will produce: "Her"
     *</p>
     * <p>
     * If number is bigger than the size of the String, the whole string is kept : <br/>
     * &nbsp;<code>truncate("Hernandez", 24)</code><br/>
     * will produce: "Hernandez"
     *</p>
     * <p>If number==0, the function returns an empty string.</p>
     * @param originalString
     * @param number
     * @return a new smaller String.
     * @throws IllegalArgumentException if number<0 or original is null
     */
    public static String truncate(String original, int number) {
        if (number < 0) {
            throw new IllegalArgumentException("number :" + number + " is <0");
        }
        if (original == null) {
            throw new IllegalArgumentException("original string is null");
        }
        String newLastName = original.length() >= number ? original.substring(0, number) : original;
        return newLastName;

    }

    /**
     * If stringToTes contains any character in 'characatersToTest', the function returns true, false if not
     * @param stringToTest
     * @param charatersToTest
     * @return true if stringToTes contains any character in 'characatersToTest'
     * @throws IllegalArgumentException if charactersToTest is null or empty
     */
    public static boolean containsCharacter(String stringToTest, String charatersToTest) {

        if (charatersToTest == null) {
            throw new IllegalArgumentException("characters is null");
        }
        if (charatersToTest.length() == 0) {
            throw new IllegalArgumentException("No character to Test");
        }

        for (int i = 0; i < charatersToTest.length(); i++) {
            char c = charatersToTest.charAt(i);

            if (stringToTest.contains(String.valueOf(c))) {
                return true;
            }
        }

        return false;

    }

  


    /**
     * Returns the concatenation of the absolute and relative paths, adding a "/" character between them if needed
     * Calling addPath(uri, "/") ensures that the path will finish with only one "/" (as long as uri doesn't finishes with more than one "/")
     * @param absolute
     * @param relative
     * @return
     */
    public static String addPath(String absolute, String relative){
        return removeTrailingCharacters(absolute, '/')+"/"+removeStartingCharacters(relative, '/');
    }

    /**
     * Add the protocol to the String
     * @param protocol
     * @param uri
     * @return a new Stirng with the protocol
     */
    public static String addProtocol(String protocol, String uri){
        String worker=removeTrailingCharacters(protocol, '/');
        worker=removeTrailingCharacters(worker, ':');
        return worker+"://"+removeStartingCharacters(uri, '/');
    }

    /**
     * Needed for Gwt Compatibility : GWT does not yet provide a getSimpleClassName
     * @param o
     * @return
     */
    public static String getSimpleClassName(Object o) {
        String className = o.getClass().getName();
        return className.substring(
                className.lastIndexOf(".") + 1, className.length());

    }

    /**
     * Return a String that starts with an Uppercase character, and ends with LowerCase characters
     * strictCapitalize("johnDoe") returns Johndoe
     * @param string string to capitalize
     * @return a String that starts with an Uppercase character, and ends with LowerCase characters
     * @see #simpleCapitalize(java.lang.String) 
     */
    public static String strictCapitalize(String str) {
        if (str == null){
            throw new IllegalArgumentException("String is null");
        }
        if (str.length() == 0) {
            return str;
        }
        String worker = str.toLowerCase();
        return worker.substring(0, 1).toUpperCase() + worker.substring(1);
    }

    /**
     * Capitalize the first letter, and doesn't touch any other
     * simpleCapitalize("johnDoe") returns JohnDoe
     * @param string string to capitalize
     * @return the same string with capitalized first letter
     * @see #strictCapitalize(java.lang.String) 
     */
    public static String simpleCapitalize(String str){
        if (str == null){
            throw new IllegalArgumentException("String is null");
        }
        if (str.length() == 0) {
            return str;
        }
        String work = new String(str);
        return work.substring(0, 1).toUpperCase() + work.substring(1);
    }

    /**
     * TODO 1 : work on this ; Use StringTokenizer
     * <p>Splits the provided text into an array ,* separators specified.</p>
     *
     * <p>The separator is not included in the returned String array.
     * Adjacent separators are treated as one separator.</p>
     *
     * <pre>     
     * StringUtils.split("ab de fg", " ")   = ["ab", "de", "fg"]
     * StringUtils.split("ab   de fg", " ") = ["ab", "cd", "ef"]
     * StringUtils.split("ab:cd:ef", ":")    = ["ab", "cd", "ef"]
     * </pre>
     *
     * @param string  the String to parse, may be null
     * @param separatorChars  the characters used as the delimiters
     * @return an array of parsed Strings
     * @throws IllegalArgumentException if string or separatorChars is null, or if separatorChars is empty
     */
    public static String[] split(String string, String separatorChars){
        if (string == null){
            throw new IllegalArgumentException("string argument is null");
        }
        if (separatorChars == null || separatorChars.length() == 0){
            throw new IllegalArgumentException("separators is null or empty");
        }

        List<String> resultList = new ArrayList<String>();
        String worker =new String(string);
        String firstSeparator = separatorChars.substring(0, 1);
        assert firstSeparator.length() == 1;

        char[] charArray = separatorChars.toCharArray();
        //We replace multiple instance of other separator by only one firstSeparator
        for (int i = 1 ; i < charArray.length ; i++){
            String pattern = "("+charArray[i]+")+";
            worker = worker.replaceAll(pattern, firstSeparator);
        }
        
        //One more pass for the first separator
        String pattern = "("+firstSeparator+")+";
        worker = worker.replaceAll(pattern, firstSeparator);

        System.out.println("separator : "+firstSeparator+" ; worker : "+worker);
        Collections.addAll(resultList, worker.split(firstSeparator) );
        return (String[]) resultList.toArray(new String[resultList.size()]);       
    }

    /**
     * @todo3 : to be tested
     * Join elements
     * @param strings
     * @param join
     * @return
     */
    public static String join (Object [] strings, String joint){

        if (strings == null){
            throw new IllegalArgumentException("strings array is null");
        }
        if (joint == null){
            throw new IllegalArgumentException("No joint ; use empty String instead of null");
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0 ; i < strings.length ; i++){
            sb.append(strings[i].toString());
            //if not last
            if (i < strings.length - 1 && joint.length()>0){
                sb.append(joint);
            }
        }
        return sb.toString();
    }

    public static String defaultJoints = " _-";
    
    /**
     * Transfom joints in capital characters
     * Chateau De Versailles => ChateauDeVersaille
     * white_house => whiteHouse  (House is now capitalized)
     * groovyStyle_grails => groovyStyleGrails (inside capitals are untouched)
     * One difference with Java style is that the first letter might stay a capital
     *
     * If specifiedJoints == null, the method uses default ones : " _-", thought this
     * can be changed with the {@link StringUtils#defaultJoints}
     *
     * @param string
     * @return
     */
    public static String normalize(String string, String specifiedJoints){
        if (specifiedJoints == null){
            specifiedJoints = defaultJoints;
        }

        String worker = replaceAny(string, specifiedJoints, " ");
        String [] array = split(worker, " ");
        for (int i = 0 ; i < array.length ; i++){
            String s = array[i];
            if (i>0){
                array[i] = simpleCapitalize(s);
            }
            
        }

        return join(array, "");
    }




}

   
    
    
    
    
    
    
  








Related examples in the same category

1.Methods for number conversion and parsing
2.Get Digit Number String
3.Convert to numbers
4.Check Number properties and convert from Number
5.Check if number are in a given range
6.Various number-related routines and classes that are frequently used
7.Turns a string value into a java.lang.Number.
8.Provides IEEE-754r variants of NumberUtils methods.
9.Checks whether the String a valid Java number.
10.Specifies sizes of various types in bytes.
11.Class to represent 16-bit unsigned integers.
12.Implements an integer object wrapper which allows changing the integer value.Implements an integer object wrapper which allows changing the integer value.
13.Mixed Radix Number
14.This class allows a number to be converted to it's unsigned value.
15.Ternary Numnber
16.Implements a long object wrapper which allows changing the long value.
17.Convert the given number into an instance of the given target class.