📄 calcs.java
字号:
/* Calcs.java{{IS_NOTE Purpose: Description: History: Mon Sep 25 14:34:48 2006, Created by tomyeh}}IS_NOTECopyright (C) 2006 Potix Corporation. All Rights Reserved.{{IS_RIGHT This program is distributed under GPL Version 2.0 in the hope that it will be useful, but WITHOUT ANY WARRANTY.}}IS_RIGHT*/package org.zkoss.math;import java.util.Date;import java.util.Map;import java.math.BigDecimal;import java.math.BigInteger;import java.text.ParseException;import org.zkoss.mesg.MCommon;import org.zkoss.lang.D;import org.zkoss.lang.Objects;import org.zkoss.lang.Strings;import org.zkoss.math.BigDecimals;import org.zkoss.math.BigIntegers;import org.zkoss.text.DateFormats;/** * Calculation utilities. * * @author tomyeh */public class Calcs { protected Calcs() {} /** Test whether an object is true. A numeric object is true, if it is * not zero (be careful with Double). A vector is true, if it * contains at least one non-zero item. * * <p>If the object is a string, true is returned if the string * is not null and not empty. * Note: Boolean.valueOf() tests whether a string is "true". */ public static boolean booleanValueOf(Object obj) { if (obj == null || obj == Objects.UNKNOWN) return false; if (obj instanceof String) return ((String)obj).length() > 0; if (obj instanceof Boolean) return ((Boolean)obj).booleanValue(); if (obj instanceof Integer) return ((Integer)obj).intValue() != 0; if (obj instanceof Long) return ((Long)obj).longValue() != 0; if (obj instanceof BigDecimal) return ((BigDecimal)obj).compareTo(BigDecimals.ZERO) != 0; if (obj instanceof Double) { final double d = ((Double)obj).doubleValue(); return d != 0.0 && d != Double.NaN; } if (obj instanceof Byte) return ((Byte)obj).byteValue() != 0; if (obj instanceof Short) return ((Short)obj).shortValue() != 0; if (obj instanceof Character) return ((Character)obj).charValue() != (char)0; if (obj instanceof Float) { final float f = ((Float)obj).floatValue(); return f != 0.0F && f != Float.NaN; } if (obj instanceof BigInteger) return !((BigInteger)obj).equals(BigInteger.ZERO); return true; //non-null object is true } /** * Converts an object to an integer, * * @exception NumberFormatException if failed to convert to a number or date */ public static final int intValueOf(Object obj) { Object val = valueOf(obj); if (val instanceof Integer) { return ((Integer)val).intValue(); } else if (val instanceof BigDecimal) { return ((BigDecimal)val).intValue(); } else if (val instanceof Long) { return ((Long)val).intValue(); } else if (val instanceof Double) { return ((Double)val).intValue(); } else { //Date return (int)((Date)val).getTime(); } } /** * Converts an object to an long integer, * * @exception NumberFormatException if failed to convert to a number or date */ public static final long longValueOf(Object obj) { Object val = valueOf(obj); if (val instanceof Integer) { return ((Integer)val).longValue(); } else if (val instanceof BigDecimal) { return ((BigDecimal)val).longValue(); } else if (val instanceof Long) { return ((Long)val).longValue(); } else if (val instanceof Double) { return ((Double)val).longValue(); } else { //Date return (long)((Date)val).getTime(); } } /** Tests whether obj is a numeric object. * * @param extend whether to consider Date, Character and Boolean as * a numeric object. * @link org.zkoss.lang.Classes#isNumeric *//* public static boolean isNumeric(Object obj, boolean extend) { if (obj == null) return false; if (obj instanceof Number) return true; return extend && ((obj instanceof Date) || (obj instanceof Boolean) || (obj instanceof Character)); }*/ /** Tests whether a string is numerable. *//* public static final boolean isNumerable(String s) { try { valueOf(s); return true; } catch (NumberFormatException ex) { return false; } }*/ /** Converts an object to a number, either Integer, Long, * Double, BigDecimal, or Date. * <p>Note: Date is considered as a number, so you can do arithmetic on it. * * <p>Accepts 0x, #... * * <p>If the object is null, Integer(0) is returned. * If the object is Boolean, Byte, Character, or Short, * it will be promoted to Integer. * If it is not a number object, it is converted to a string first. * * @return Integer, Long, Double, BigDecimal or Date that best matched */ public static Object valueOf(Object obj) { if (obj == null || obj == Objects.UNKNOWN) return Objects.ZERO_INTEGER; if ((obj instanceof Integer) || (obj instanceof BigDecimal) || (obj instanceof Long) || (obj instanceof Date) || (obj instanceof Double)) return obj; if (obj instanceof Byte) return new Integer(((Byte)obj).intValue()); if (obj instanceof Short) return new Integer(((Short)obj).intValue()); if (obj instanceof Character) return new Integer(((Character)obj).charValue()); if (obj instanceof Float) return new Double(((Float)obj).doubleValue()); if (obj instanceof BigInteger) { BigInteger v = (BigInteger)obj; if (v.bitCount() <= 32) return new Integer(v.intValue()); if (v.bitCount() <= 64) return new Long(v.longValue()); throw new UnsupportedOperationException("Not support: BigInteger's bit count > 64, " + v); } if (obj instanceof Boolean) return new Integer(((Boolean)obj).booleanValue() ? 1: 0); return valueOf(obj.toString()); } /** * Converts a string to a number, either Integer, Long, Double, * Bigdecimal, or Date. * * <p>Accepts 0x, #... * * <p>Implementation Note:<br> * Integer.decode cannot handle '+', ' ' and consecutive '-' correctly, * so we have to simplify the format first. * * @exception NumberFormatException if failed to convert to a number or date */ public static final Object valueOf(String s) { if (s == null) return Objects.ZERO_INTEGER; boolean dot = false, exp = false; if (!inHexFormat(s)) { int k = 0; char[] buf = new char[s.length()]; for (int j = 0; j < buf.length; ++j) { char cc = s.charAt(j); switch (cc) { case '-': if (k > 0 && buf[k - 1] == '-') { --k; //remove consecutive - continue; //skip } break; case ' ': case '+': continue; //skip case '.': if (dot || exp) return toDate(s); //not a number dot = true; break; case 'e': case 'E': if (exp) return toDate(s); //not a number exp = true; break; default: if (cc < '0' || cc > '9') return toDate(s); //not a number break; } buf[k++] = cc; //correct, store it } if (k == 0) return Objects.ZERO_INTEGER; if (k < buf.length) s = new String(buf, 0, k); } if (exp) { return Double.valueOf(s); } else if (dot) { return new BigDecimal(s); } else { try { return Integer.decode(s); } catch (NumberFormatException ex) { //overflow? or format? } return Long.decode(s); } } private static final boolean inHexFormat(String s) { int b = Strings.skipWhitespaces(s, 0); int e = Strings.skipWhitespacesBackward(s, Integer.MAX_VALUE); if (b >= e) //less than two characters return false; char cc = s.charAt(e); if (cc < '0' || cc > '9') //the last one must be a digit return false; cc = s.charAt(b); if (cc == '#') return true; if (cc != '0') return false; cc = s.charAt(b + 1); return cc == 'x' || cc == 'X'; } private static final Date toDate(String s) { try { return DateFormats.parse(s.trim()); } catch (ParseException ex) { throw new NumberFormatException(ex.getMessage()); } } /** Zero init an object. * * <p>It accepts Boolean, Byte, Character, Short, Integer, * Long, Float, Double, BigDecimal, and String. * All other types will be converted to String first. * Then, converted to either Integer, Long, Double or BigDecimal, * depending its format. * * <p>The returned result is either Integer, Long, Double or BigDecimal. */ public static final Object zero(Object obj) { if (obj == null || obj == Objects.UNKNOWN) return Objects.ZERO_INTEGER; obj = valueOf(obj); if (obj instanceof Integer) return Objects.ZERO_INTEGER; else if (obj instanceof Long) return Objects.ZERO_LONG; else if (obj instanceof Double) return Objects.ZERO_DOUBLE; else if (obj instanceof Date) return Objects.ZERO_LONG; else //BigDecimal return Objects.ZERO_BIG_DECIMAL; } /** Promotes an object, obj, by referencing another one, ref. * * <p>NOTE: you must call valueOf before calling this method, because * it examines only possible classes that might be returned by valueOf. * * <p>Note: If ref is Date but obj is not, obj is promoted to Long * instead of Date. *//* private static final Object promote(Object obj, Object ref) { if (obj instanceof Integer) { //int + bigdec => bigdec //int + double => double //int + long => long //int + date => long if (ref instanceof BigDecimal) return BigDecimals.toBigDecimal(((Integer)obj).intValue()); else if (ref instanceof Double) return new Double(((Integer)obj).intValue()); else if ((ref instanceof Long) || (ref instanceof Date)) return new Long(((Integer)obj).intValue()); return obj; } else if (obj instanceof Long) { //long + bigdec => bigdec //long + double => double if (ref instanceof BigDecimal) return BigDecimals.toBigDecimal(((Long)obj).longValue()); else if (ref instanceof Double) return new Double(((Long)obj).longValue()); return obj; } else if (obj instanceof BigDecimal) { //bigdec + double => double if (ref instanceof Double) return new Double(((BigDecimal)obj).doubleValue()); return obj; } else if (obj instanceof Double) { //double + xxx => double return obj; } else { //Date assert D.OFF || (obj instanceof Date): "valueOf must be called before promote: "+obj; //date + int => long //date + long => long //date + bigdec => bigdec //date + double => double if ((ref instanceof Integer) || (ref instanceof Long)) return new Long(((Date)obj).getTime()); else if (ref instanceof BigDecimal) return BigDecimals.toBigDecimal(((Date)obj).getTime()); else if (ref instanceof Double) return new Double(((Date)obj).getTime()); return obj; } }*/ /** Negates an object. * * <p>It accepts Boolean, Byte, Character, Short, Integer, * Long, Float, Double, BigDecimal, and String. * All other types will be converted to String first. * Then, converted to either Integer, Long, Double or BigDecimal, * depending its format. * * <p>The returned result is either Integer, Long, Double or BigDecimal. *//* public static final Object negate(Object obj) { if (obj == null || obj == Objects.UNKNOWN) return Objects.ZERO_INTEGER; obj = valueOf(obj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -