Jelajahi Sumber

Core: Parse decimal 'e' as 'E' [#565]

gnosygnu 4 tahun lalu
induk
melakukan
6ed7659b4d
2 mengubah file dengan 149 tambahan dan 128 penghapusan
  1. 73 55
      100_core/src/gplx/Decimal_adp_.java
  2. 76 73
      100_core/src/gplx/Decimal_adp__tst.java

+ 73 - 55
100_core/src/gplx/Decimal_adp_.java

@@ -1,6 +1,6 @@
 /*
 XOWA: the XOWA Offline Wiki Application
-Copyright (C) 2012-2017 gnosygnu@gmail.com
+Copyright (C) 2012-2020 gnosygnu@gmail.com
 
 XOWA is licensed under the terms of the General Public License (GPL) Version 3,
 or alternatively under the terms of the Apache License Version 2.0.
@@ -13,57 +13,75 @@ The terms of each license can be found in the source code repository:
 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
 Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
 */
-package gplx;
-import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
-import java.text.NumberFormat;
-import java.text.ParseException;
-import java.util.Locale;
-public class Decimal_adp_ {
-	public static final String Cls_val_name = "decimal";
-	public static final    Class<?> Cls_ref_type = Decimal_adp.class;
-	public static Decimal_adp as_(Object obj) {return obj instanceof Decimal_adp ? (Decimal_adp)obj : null;}
-	public static final    Decimal_adp Zero = new Decimal_adp(0);
-	public static final    Decimal_adp One = new Decimal_adp(1);
-	public static final    Decimal_adp Neg1 = new Decimal_adp(-1);
-	public static final    Decimal_adp Const_e = Decimal_adp_.double_(Math_.E);
-	public static final    Decimal_adp Const_pi = Decimal_adp_.double_(Math_.Pi);
-	public static Decimal_adp base1000_(long v) {return divide_(v, 1000);}
-	public static Decimal_adp parts_1000_(long num, int frc) {return divide_((num * (1000)) + frc, 1000);}
-	public static Decimal_adp parts_(long num, int frc) {
-		//			int log10 = frc == 0 ? 0 : (Math_.Log10(frc) + 1);
-		//			int pow10 = (int)Math_.Pow(10, log10);
-		int pow10 = XtoPow10(frc);
-		return divide_((num * (pow10)) + frc, pow10);
-	}
-	public static Decimal_adp cast(Object obj) {return (Decimal_adp)obj;}
-	static int XtoPow10(int v) {
-		if		(v >		-1 && v <            10) return 10;
-		else if (v >		 9 && v <           100) return 100;
-		else if (v >		99 && v <          1000) return 1000;
-		else if (v >	   999 && v <         10000) return 10000;
-		else if (v >	  9999 && v <        100000) return 100000;
-		else if (v >	 99999 && v <       1000000) return 1000000;
-		else if (v >	999999 && v <      10000000) return 10000000;
-		else if (v >   9999999 && v <     100000000) return 100000000;
-		else if (v >  99999999 && v <    1000000000) return 1000000000;
-		else throw Err_.new_wo_type("value must be between 0 and 1 billion", "v", v);
-	}
-	public static String CalcPctStr(long dividend, long divisor, String fmt) {
-		if (divisor == 0) return "%ERR";
-		return Decimal_adp_.float_(Float_.Div(dividend, divisor) * 100).To_str(fmt) + "%";
-	}
-	public static Decimal_adp divide_safe_(long lhs, long rhs) {return rhs == 0 ? Zero : divide_(lhs, rhs);}
-		public static Decimal_adp divide_(long lhs, long rhs) {
		return new Decimal_adp(new BigDecimal(lhs).divide(new BigDecimal(rhs), Gplx_rounding_context));
	}
	public static Decimal_adp int_(int v) {return new Decimal_adp(new BigDecimal(v));}
	public static Decimal_adp long_(long v) {return new Decimal_adp(new BigDecimal(v));}
-	public static Decimal_adp float_(float v) {return new Decimal_adp(new BigDecimal(v));}
	public static Decimal_adp double_(double v) {return new Decimal_adp(new BigDecimal(v));}
-	public static Decimal_adp double_thru_str_(double v) {return new Decimal_adp(BigDecimal.valueOf(v));}
-	public static Decimal_adp db_(Object v) {return new Decimal_adp((BigDecimal)v);}
	public static Decimal_adp parse(String raw) {
-		try {
-	        DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(Locale.US);	// always parse as US format; EX:".9" should not be ",9" in german; DATE:2016-01-31
-	        nf.setParseBigDecimal(true);
-	        BigDecimal bd = (BigDecimal)nf.parse(raw);
-			return new Decimal_adp(bd);
-		} catch (ParseException e) {
-			throw Err_.new_("Decimal_adp_", "parse to decimal failed", "raw", raw);
-		}
-	}
	public static Decimal_adp pow_10_(int v) {return new Decimal_adp(new BigDecimal(1).scaleByPowerOfTen(v));}
-	public static final MathContext RoundDownContext = new MathContext(0, RoundingMode.DOWN);
	public static final MathContext Gplx_rounding_context = new MathContext(14, RoundingMode.HALF_UP);	// changed from 28 to 14; DATE:2015-07-31
	}
+package gplx;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Locale;
+
+public class Decimal_adp_ {
+	public static final String Cls_val_name = "decimal";
+	public static final    Class<?> Cls_ref_type = Decimal_adp.class;
+	public static Decimal_adp as_(Object obj) {return obj instanceof Decimal_adp ? (Decimal_adp)obj : null;}
+	public static final    Decimal_adp Zero = new Decimal_adp(0);
+	public static final    Decimal_adp One = new Decimal_adp(1);
+	public static final    Decimal_adp Neg1 = new Decimal_adp(-1);
+	public static final    Decimal_adp Const_e = Decimal_adp_.double_(Math_.E);
+	public static final    Decimal_adp Const_pi = Decimal_adp_.double_(Math_.Pi);
+	public static Decimal_adp base1000_(long v) {return divide_(v, 1000);}
+	public static Decimal_adp parts_1000_(long num, int frc) {return divide_((num * (1000)) + frc, 1000);}
+	public static Decimal_adp parts_(long num, int frc) {
+		//			int log10 = frc == 0 ? 0 : (Math_.Log10(frc) + 1);
+		//			int pow10 = (int)Math_.Pow(10, log10);
+		int pow10 = XtoPow10(frc);
+		return divide_((num * (pow10)) + frc, pow10);
+	}
+	public static Decimal_adp cast(Object obj) {return (Decimal_adp)obj;}
+	static int XtoPow10(int v) {
+		if		(v >		-1 && v <            10) return 10;
+		else if (v >		 9 && v <           100) return 100;
+		else if (v >		99 && v <          1000) return 1000;
+		else if (v >	   999 && v <         10000) return 10000;
+		else if (v >	  9999 && v <        100000) return 100000;
+		else if (v >	 99999 && v <       1000000) return 1000000;
+		else if (v >	999999 && v <      10000000) return 10000000;
+		else if (v >   9999999 && v <     100000000) return 100000000;
+		else if (v >  99999999 && v <    1000000000) return 1000000000;
+		else throw Err_.new_wo_type("value must be between 0 and 1 billion", "v", v);
+	}
+	public static String CalcPctStr(long dividend, long divisor, String fmt) {
+		if (divisor == 0) return "%ERR";
+		return Decimal_adp_.float_(Float_.Div(dividend, divisor) * 100).To_str(fmt) + "%";
+	}
+	public static Decimal_adp divide_safe_(long lhs, long rhs) {return rhs == 0 ? Zero : divide_(lhs, rhs);}
+		public static Decimal_adp divide_(long lhs, long rhs) {
+		return new Decimal_adp(new BigDecimal(lhs).divide(new BigDecimal(rhs), Gplx_rounding_context));
+	}
+	public static Decimal_adp int_(int v) {return new Decimal_adp(new BigDecimal(v));}
+	public static Decimal_adp long_(long v) {return new Decimal_adp(new BigDecimal(v));}
+	public static Decimal_adp float_(float v) {return new Decimal_adp(new BigDecimal(v));}
+	public static Decimal_adp double_(double v) {return new Decimal_adp(new BigDecimal(v));}
+	public static Decimal_adp double_thru_str_(double v) {return new Decimal_adp(BigDecimal.valueOf(v));}
+	public static Decimal_adp db_(Object v) {return new Decimal_adp((BigDecimal)v);}
+	public static Decimal_adp parse(String raw) {
+		try {
+	        DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(Locale.US);	// always parse as US format; EX:".9" should not be ",9" in german; DATE:2016-01-31
+	        nf.setParseBigDecimal(true);
+	        // 2020-08-27|ISSUE#:565|Parse 'e' as 'E'; PAGE:en.w:Huntington_Plaza
+	        if (raw.contains("e")) {
+	        	raw = raw.replace("e", "E");
+	        }
+	        BigDecimal bd = (BigDecimal)nf.parse(raw);
+			return new Decimal_adp(bd);
+		} catch (ParseException e) {
+			throw Err_.new_("Decimal_adp_", "parse to decimal failed", "raw", raw);
+		}
+	}
+	public static Decimal_adp pow_10_(int v) {return new Decimal_adp(new BigDecimal(1).scaleByPowerOfTen(v));}
+	public static final MathContext RoundDownContext = new MathContext(0, RoundingMode.DOWN);
+	public static final MathContext Gplx_rounding_context = new MathContext(14, RoundingMode.HALF_UP);	// changed from 28 to 14; DATE:2015-07-31
+	}

+ 76 - 73
100_core/src/gplx/Decimal_adp__tst.java

@@ -1,6 +1,6 @@
 /*
 XOWA: the XOWA Offline Wiki Application
-Copyright (C) 2012-2017 gnosygnu@gmail.com
+Copyright (C) 2012-2020 gnosygnu@gmail.com
 
 XOWA is licensed under the terms of the General Public License (GPL) Version 3,
 or alternatively under the terms of the Apache License Version 2.0.
@@ -13,75 +13,78 @@ The terms of each license can be found in the source code repository:
 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
 Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
 */
-package gplx;
-import org.junit.*;
-public class Decimal_adp__tst {
-	private final    Decimal_adp__fxt fxt = new Decimal_adp__fxt();
-	@Test  public void divide_() {
-		fxt.Test_divide(1, 1000, "0.001");
-		fxt.Test_divide(1, 3, "0.33333333333333");	
-		fxt.Test_divide(1, 7, "0.14285714285714");	
-	}
-	@Test  public void base1000_() {
-		fxt.Test_base_1000(1000, "1");
-		fxt.Test_base_1000(1234, "1.234");
-		fxt.Test_base_1000(123, "0.123");
-	}
-	@Test  public void parts_() {
-		fxt.Test_parts(1, 0, "1");
-		fxt.Test_parts(1, 2, "1.2");
-		fxt.Test_parts(1, 23, "1.23");
-		fxt.Test_parts(123, 4567, "123.4567");
-	}
-	@Test  public void parse() {
-		fxt.Test_parse("1", "1");
-		fxt.Test_parse("1.2", "1.2");
-		fxt.Test_parse("0.1", "0.1");
-		fxt.Test_parse("1.2E1", "12");
-	}
-	@Test  public void Truncate_decimal() {
-		fxt.Test_truncate_decimal("1", "1");
-		fxt.Test_truncate_decimal("1.1", "1");
-		fxt.Test_truncate_decimal("1.9", "1");
-	}
-	@Test  public void Fraction1000() {
-		fxt.Test_frac_1000(1, 1000, 1);			// 0.001
-		fxt.Test_frac_1000(1, 3, 333);			// 0.33333333
-		fxt.Test_frac_1000(1234, 1000, 234);		// 1.234
-		fxt.Test_frac_1000(12345, 10000, 234);	// 1.2345
-	}
-	@Test  public void Lt() {
-		fxt.Test_comp_lt(1,123, 2, true);
-		fxt.Test_comp_lt(1,99999999, 2, true);
-	}
-	@Test  public void To_str_fmt() {
-		fxt.Test_to_str_fmt(1, 2, "0.0", "0.5");
-		fxt.Test_to_str_fmt(1, 3, "0.0", "0.3");
-		fxt.Test_to_str_fmt(10000, 7, "0,000.000", "1,428.571");
-		fxt.Test_to_str_fmt(1, 2, "00.00", "00.50");
-	}
-	@Test  public void Round() {
-		fxt.Test_round("123.456",  3, "123.456");
-		fxt.Test_round("123.456",  2, "123.46");
-		fxt.Test_round("123.456",  1, "123.5");
-		fxt.Test_round("123.456",  0, "123");
-		fxt.Test_round("123.456", -1, "120");
-		fxt.Test_round("123.456", -2, "100");
-		fxt.Test_round("123.456", -3, "0");
-
-		fxt.Test_round("6", -1, "10");
-		fxt.Test_round("5", -1, "10");
-		fxt.Test_round("6", -2, "0");
-	}
-}
-class Decimal_adp__fxt {
-	public void Test_divide(int lhs, int rhs, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).To_str());}
-	public void Test_base_1000(int val, String expd) {Tfds.Eq(expd, Decimal_adp_.base1000_(val).To_str());}
-	public void Test_parts(int num, int fracs, String expd) {Tfds.Eq(expd, Decimal_adp_.parts_(num, fracs).To_str());}
-	public void Test_parse(String raw, String expd) {Tfds.Eq(expd, Decimal_adp_.parse(raw).To_str());}
-	public void Test_truncate_decimal(String raw, String expd) {Tfds.Eq(Decimal_adp_.parse(expd).To_str(), Decimal_adp_.parse(raw).Truncate().To_str());}
-	public void Test_frac_1000(int lhs, int rhs, int expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).Frac_1000());}
-	public void Test_comp_lt(int lhsNum, int lhsFrc, int rhs, boolean expd) {Tfds.Eq(expd, Decimal_adp_.parts_(lhsNum, lhsFrc).Comp_lt(rhs));}
-	public void Test_to_str_fmt(int l, int r, String fmt, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(l, r).To_str(fmt));}
-	public void Test_round(String raw, int places, String expd) {Tfds.Eq_str(expd, Decimal_adp_.parse(raw).Round(places).To_str(), "round");}
-}
+package gplx;
+
+import org.junit.*;
+
+public class Decimal_adp__tst {
+	private final    Decimal_adp__fxt fxt = new Decimal_adp__fxt();
+	@Test  public void divide_() {
+		fxt.Test_divide(1, 1000, "0.001");
+		fxt.Test_divide(1, 3, "0.33333333333333");	
+		fxt.Test_divide(1, 7, "0.14285714285714");	
+	}
+	@Test  public void base1000_() {
+		fxt.Test_base_1000(1000, "1");
+		fxt.Test_base_1000(1234, "1.234");
+		fxt.Test_base_1000(123, "0.123");
+	}
+	@Test  public void parts_() {
+		fxt.Test_parts(1, 0, "1");
+		fxt.Test_parts(1, 2, "1.2");
+		fxt.Test_parts(1, 23, "1.23");
+		fxt.Test_parts(123, 4567, "123.4567");
+	}
+	@Test  public void parse() {
+		fxt.Test_parse("1", "1");
+		fxt.Test_parse("1.2", "1.2");
+		fxt.Test_parse("0.1", "0.1");
+		fxt.Test_parse("1.2E1", "12");
+		fxt.Test_parse("1.2e1", "12"); // 2020-08-27|ISSUE#:565|Parse 'e' as 'E'; PAGE:en.w:Huntington_Plaza
+	}
+	@Test  public void Truncate_decimal() {
+		fxt.Test_truncate_decimal("1", "1");
+		fxt.Test_truncate_decimal("1.1", "1");
+		fxt.Test_truncate_decimal("1.9", "1");
+	}
+	@Test  public void Fraction1000() {
+		fxt.Test_frac_1000(1, 1000, 1);			// 0.001
+		fxt.Test_frac_1000(1, 3, 333);			// 0.33333333
+		fxt.Test_frac_1000(1234, 1000, 234);		// 1.234
+		fxt.Test_frac_1000(12345, 10000, 234);	// 1.2345
+	}
+	@Test  public void Lt() {
+		fxt.Test_comp_lt(1,123, 2, true);
+		fxt.Test_comp_lt(1,99999999, 2, true);
+	}
+	@Test  public void To_str_fmt() {
+		fxt.Test_to_str_fmt(1, 2, "0.0", "0.5");
+		fxt.Test_to_str_fmt(1, 3, "0.0", "0.3");
+		fxt.Test_to_str_fmt(10000, 7, "0,000.000", "1,428.571");
+		fxt.Test_to_str_fmt(1, 2, "00.00", "00.50");
+	}
+	@Test  public void Round() {
+		fxt.Test_round("123.456",  3, "123.456");
+		fxt.Test_round("123.456",  2, "123.46");
+		fxt.Test_round("123.456",  1, "123.5");
+		fxt.Test_round("123.456",  0, "123");
+		fxt.Test_round("123.456", -1, "120");
+		fxt.Test_round("123.456", -2, "100");
+		fxt.Test_round("123.456", -3, "0");
+
+		fxt.Test_round("6", -1, "10");
+		fxt.Test_round("5", -1, "10");
+		fxt.Test_round("6", -2, "0");
+	}
+}
+class Decimal_adp__fxt {
+	public void Test_divide(int lhs, int rhs, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).To_str());}
+	public void Test_base_1000(int val, String expd) {Tfds.Eq(expd, Decimal_adp_.base1000_(val).To_str());}
+	public void Test_parts(int num, int fracs, String expd) {Tfds.Eq(expd, Decimal_adp_.parts_(num, fracs).To_str());}
+	public void Test_parse(String raw, String expd) {Tfds.Eq(expd, Decimal_adp_.parse(raw).To_str());}
+	public void Test_truncate_decimal(String raw, String expd) {Tfds.Eq(Decimal_adp_.parse(expd).To_str(), Decimal_adp_.parse(raw).Truncate().To_str());}
+	public void Test_frac_1000(int lhs, int rhs, int expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).Frac_1000());}
+	public void Test_comp_lt(int lhsNum, int lhsFrc, int rhs, boolean expd) {Tfds.Eq(expd, Decimal_adp_.parts_(lhsNum, lhsFrc).Comp_lt(rhs));}
+	public void Test_to_str_fmt(int l, int r, String fmt, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(l, r).To_str(fmt));}
+	public void Test_round(String raw, int places, String expd) {Tfds.Eq_str(expd, Decimal_adp_.parse(raw).Round(places).To_str(), "round");}
+}