/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.ui.util; import static java.lang.Math.abs; import static java.lang.Math.pow; public class NumberUtils { private NumberUtils() { } public static long safeParseLong(String s, long defaultLong) { try { return Long.parseLong(s); } catch (Exception e) { return defaultLong; } } public static int safeParseInt(String s, int defaultInt) { if (s == null || "".equals(s)) //$NON-NLS-1$ return defaultInt; int result = 0; int radix = 10; int i = 0, max = s.length(); int limit = -Integer.MAX_VALUE; int multmin = limit / radix; int digit; if (max > 0) { if (i < max) { digit = Character.digit(s.charAt(i++), radix); if (digit < 0) { return defaultInt; } else { result = -digit; } } while (i < max) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(s.charAt(i++), radix); if (digit < 0) { return -result; } if (result < multmin) { return -result; } result *= radix; if (result < limit + digit) { return -result; } result -= digit; } return -result; } return defaultInt; } /** * Parses the specified string argument to an unsigned decimal integer. If * the string starts with non-digital characters ( '-' included ), -1 is * returned. If the string starts with digital characters but ends with * non-digital ones, the value of the digital part is returned. * * @param s * a <code>String</code> containing the <code>int</code> * representation to be parsed. * @return the integer value represented by the argument in decimal. */ public static int safeParseInt(String s) { return safeParseInt(s, -1); } public static double safeParseDouble(String s) { return safeParseDouble(s, 0); } public static double safeParseDouble(String s, double defaultDouble) { if (s == null || "".equals(s)) //$NON-NLS-1$ return defaultDouble; try { return Double.parseDouble(s); } catch (Exception e) { } return defaultDouble; } public static String toLetter(int digit, char start, int total) { if (digit <= total) { return String.valueOf((char) (digit + start - 1)); } int x = digit / total; int y = digit - x * total; if (y == 0) { y = total; x--; } return toLetter(x, start, total) + toLetter(y, start, total); } public static final int DEFAULT_MAX_ROUND = 10000; public static final double DEFAULT_EPSILONG = 0.00000001; public static double newton(double[] coefs, double x0) { return newton(coefs, x0, DEFAULT_MAX_ROUND, DEFAULT_EPSILONG); } /** * Find a solution to the following equation:<br> * <blockquote> * <code>a<sub>0</sub> X<sup>n</sup> + a<sub>1</sub> X<sup>n-1</sup> + ... * + a<sub>n-1</sub> X + a<sub>n</sub> = 0</code></blockquote> * * @param coefs * [ a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub> ] * @param x0 * an initial value * @param max * the maximum rounds the iteration goes * @param eps * precision controller * @return a solution to the equation near the initial value */ public static double newton(double[] coefs, double x0, int max, double eps) { if (coefs == null) throw new IllegalArgumentException("coefficient list is null"); //$NON-NLS-1$ if (coefs.length <= 1) throw new IllegalArgumentException( "coefficients are too few to calculate"); //$NON-NLS-1$ eps = abs(eps); double current = x0; double last = current; double sig = 1; int i = 0; while (abs(sig) > eps) { i++; if (i >= max) { //Logger.log("Out of max: " + Arrays.toString( coefs ) + ", x = " + current); //$NON-NLS-1$ //$NON-NLS-2$ break; } current = last - f(coefs, last) / df(coefs, last); sig = current - last; last = current; } return current; } /** * Calculate the value of polynomial. * * @param coefs * coefficients of the polynomial * @param x * variable value * @return the value of the polynomial */ static double f(double[] coefs, double x) { double y = 0; for (int i = 0; i < coefs.length; i++) { y += coefs[i] * pow(x, coefs.length - 1 - i); } return y; } /** * Calculate the value of differentiated polynomial * * @param coefs * coefficients of the polynomial * @param x * variable value * @return the value of differentiated polynomial */ static double df(double[] coefs, double x) { double y = 0; for (int i = 0; i < coefs.length - 1; i++) { y += coefs[i] * (coefs.length - 1 - i) * pow(x, coefs.length - 2 - i); } return y; } public static short bytesToShort16(byte highByte, byte lowByte) { return (short) ((highByte << 8) | (lowByte & 0xFF)); } public static enum RomanSymbols { M(1000), D(500), C(100), L(50), X(10), V(5), I(1); public final long value; private RomanSymbols(int value) { this.value = value; } } public static String toRoman(long n) { int i; StringBuilder sb = new StringBuilder(10); RomanSymbols[] symbols = RomanSymbols.values(); while (n > 0) { for (i = 0; i < symbols.length; i++) { if (symbols[i].value <= n) { int shift = i + (i % 2); if (i > 0 && shift < symbols.length && (symbols[i - 1].value - symbols[shift].value) <= n) { sb.append(symbols[shift].name()); sb.append(symbols[i - 1].name()); n = n - symbols[i - 1].value + symbols[shift].value; i = -1; } else { sb.append(symbols[i].name()); n -= symbols[i].value; i = -1; } } } } return sb.toString(); } @SuppressWarnings("nls") public static String toSimpleChinese(int n) { String num[] = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" }; String xx[] = { "十", "百", "千" }; StringBuilder sb = new StringBuilder(); int bs = 0; while ((int) (n / ((long) Math.pow(10, bs))) != 0) { bs++; } if (bs > 4) return ""; for (int i = bs - 1; i >= 0; i--) { int index = (int) (n / Math.pow(10, i)); sb.append(num[index]); if (index != 0 && i > 0) sb.append(xx[i - 1]); n -= index * Math.pow(10, i); } return sb.toString(); } @SuppressWarnings("nls") public static String toTraditionalChinese(int n) { String num[] = { "零", "壹", "貳", "參", "肆", "伍", "陸", "柒", "捌", "玖" }; String xx[] = { "拾", "佰", "仟" }; StringBuilder sb = new StringBuilder(); int bs = 0; while ((int) (n / ((long) Math.pow(10, bs))) != 0) { bs++; } if (bs > 4) return ""; for (int i = bs - 1; i >= 0; i--) { int index = (int) (n / Math.pow(10, i)); sb.append(num[index]); if (index != 0 && i > 0) sb.append(xx[i - 1]); n -= index * Math.pow(10, i); } return sb.toString(); } }