mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
Scribunto: Trim zeroes when stringifying Doubles [#697]
This commit is contained in:
parent
f122a8d8a3
commit
bdae819908
@ -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.
|
||||
@ -14,6 +14,7 @@ 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;
|
||||
|
||||
public class Double_ {
|
||||
public static final String Cls_val_name = "double";
|
||||
public static final Class<?> Cls_ref_type = Double.class;
|
||||
@ -42,7 +43,9 @@ public class Double_ {
|
||||
int v_as_int = (int)v;
|
||||
return v == v_as_int
|
||||
? Int_.To_str(v_as_int) // convert to int, and call print String to eliminate any trailing decimal places
|
||||
: Float_.To_str((float)v); // calling ((float)v).toString is better at removing trailing 0s than String.format("%g", v). note that .net .toString() handles it better; EX:2449.600000000000d; DATE:2014-07-29
|
||||
// DATE:2014-07-29; calling ((float)v).toString is better at removing trailing 0s than String.format("%g", v). note that .net .toString() handles it better; EX:2449.600000000000d
|
||||
// DATE:2020-08-12; calling ToStrByPrintF b/c better at removing trailing 0s; ISSUE#:697;
|
||||
: gplx.objects.primitives.Double_.ToStrByPrintF(v);
|
||||
}
|
||||
public static int Compare(double lhs, double rhs) {
|
||||
if (lhs == rhs) return CompareAble_.Same;
|
||||
|
@ -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,11 +13,27 @@ 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.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
|
||||
import org.junit.*;
|
||||
import gplx.langs.jsons.*;
|
||||
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*; import gplx.xowa.langs.numbers.*;
|
||||
import gplx.xowa.xtns.cldrs.*;
|
||||
package gplx.xowa.xtns.scribunto.libs;
|
||||
|
||||
import gplx.Bry_;
|
||||
import gplx.DateAdp_;
|
||||
import gplx.Datetime_now;
|
||||
import gplx.Gfo_invk_;
|
||||
import gplx.Io_mgr;
|
||||
import gplx.Keyval;
|
||||
import gplx.Keyval_;
|
||||
import gplx.Object_;
|
||||
import gplx.String_;
|
||||
import gplx.langs.jsons.Json_doc;
|
||||
import gplx.xowa.Xowe_wiki;
|
||||
import gplx.xowa.langs.Xol_lang_itm;
|
||||
import gplx.xowa.langs.msgs.Xol_msg_mgr;
|
||||
import gplx.xowa.xtns.cldrs.Cldr_name_loader_fxt;
|
||||
import gplx.xowa.xtns.scribunto.Scrib_invoke_func_fxt;
|
||||
import gplx.xowa.xtns.scribunto.Scrib_lib;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Scrib_lib_language_tst {
|
||||
@Before public void init() {
|
||||
fxt.Clear_for_lib();
|
||||
@ -98,6 +114,7 @@ public class Scrib_lib_language_tst {
|
||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_language.Invk_formatNum, Object_.Ary("en", "1234", Keyval_.Ary(Keyval_.new_("noCommafy", true))) , "1234"); // noCommafy.y
|
||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_language.Invk_formatNum, Object_.Ary("en", "1234", Keyval_.Ary(Keyval_.new_("noCommafy", false))) , "1,234"); // noCommafy.n
|
||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_language.Invk_formatNum, Object_.Ary("en", "1234", Keyval_.Ary(Keyval_.new_("noCommafy", "y"))) , "1234"); // noCommafy."y"; ISSUE#:372 DATE:2019-03-02
|
||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_language.Invk_formatNum, Object_.Ary("en", 768d / 10000000d) , "7.68E-5"); // ensure "e-05" -> "E-5" ISSUE#:697; DATE:2020-08-12
|
||||
}
|
||||
@Test public void FormatDate() {
|
||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_language.Invk_formatDate, Object_.Ary("en", "Y-m-d", "2013-03-17", false), "2013-03-17");
|
||||
|
@ -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,8 +13,100 @@ 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.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
package gplx.objects.primitives;
|
||||
|
||||
public class Double_ {
|
||||
public static final String Cls_val_name = "double";
|
||||
public static final Class<?> Cls_ref_type = Double.class;
|
||||
public static final Class<?> Cls_ref_type = Double.class;
|
||||
|
||||
public static String ToStrByPrintF(double val) {
|
||||
// call sprintf-like format; EX:"sprintf((s), "%.14g", (n));"
|
||||
return TrimZeroes(String.format("%.14g", val));
|
||||
}
|
||||
public static String TrimZeroes(String valStr) { // TEST
|
||||
// NOTE:this function was originally in LuaDouble; it was refactored for clarity, and also to handle trimming zeroes from exponent; EX:"e-05" ISSUE#:697; DATE:2020-08-12
|
||||
int valStrLen = valStr.length();
|
||||
boolean startTrimming = true; // will be set to true at end of string (12.00), or before "e" (1.00e5)
|
||||
boolean trimmingZeroes = false;
|
||||
int trimIdx = -1;
|
||||
int expIdx = -1;
|
||||
|
||||
// read backwards from end of string
|
||||
for (int i = valStrLen - 1; i > -1; i--) {
|
||||
switch (valStr.charAt(i)) {
|
||||
case '0':
|
||||
// if startTrimming is true, then enable trimmingZeroes; should only occur twice; (1) end of string ("12.00"); (2) before "e" ("1.00e5")
|
||||
if (startTrimming) {
|
||||
startTrimming = false;
|
||||
trimmingZeroes = true;
|
||||
}
|
||||
|
||||
// if trimmingZeroes, set trimIdx just before this `0`
|
||||
if (trimmingZeroes)
|
||||
trimIdx = i;
|
||||
break;
|
||||
case '1': case '2': case '3': case '4': case '5':
|
||||
case '6': case '7': case '8': case '9':
|
||||
// disable trimmingZeroes; EX: "12.30"
|
||||
trimmingZeroes = false;
|
||||
startTrimming = false; // mark startTrimming false else will gobble up zeroes before numbers; EX: "0.00001" x> "0.1"; ISSUE#:697; DATE:2020-08-11
|
||||
break;
|
||||
case '-': // ignore scientific notation or negative sign; EX: "5.0e-17", "-1"
|
||||
break;
|
||||
case 'e': // scientific notation; reset startTrimming; EX: 5.0000000000000e-17
|
||||
expIdx = i;
|
||||
startTrimming = true;
|
||||
break;
|
||||
case '.':
|
||||
// if still trimmingZeroes, and reached decimalPoint, then update trimIdx to truncate decimalPoint also; EX: "123.0000" -> "123" x> "123."
|
||||
if (trimmingZeroes)
|
||||
trimIdx = i;
|
||||
|
||||
// trimIdx has been set
|
||||
if (trimIdx != -1) {
|
||||
if (expIdx == -1) { // decimal; EX: "12.00"
|
||||
valStr = valStr.substring(0, trimIdx);
|
||||
}
|
||||
else { // exponent; "1.00e5"
|
||||
// get exponent portion; EX: "e-05"
|
||||
String expStr = valStr.substring(expIdx, valStrLen);
|
||||
int expStrLen = expStr.length();
|
||||
|
||||
// set expSymIdx to be after "e" or "e-"
|
||||
int expSymIdx = 1; // skip the "e"
|
||||
if (expSymIdx < expStrLen && !Character.isDigit(expStr.charAt(expSymIdx))) { // skip "-" if it's there
|
||||
expSymIdx++;
|
||||
}
|
||||
|
||||
// exponent can have 0s; skip them; EX: 1.1e-05
|
||||
int expNumIdx = expSymIdx;
|
||||
for (int j = expNumIdx; j < expStrLen; j++) {
|
||||
if (expStr.charAt(j) == '0') { // skip zeroes
|
||||
expNumIdx++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now stitch it together
|
||||
valStr = valStr.substring(0, trimIdx)
|
||||
+ expStr.substring(0, expSymIdx) // add "e-"
|
||||
+ expStr.substring(expNumIdx); // add numbers with any leading zeroes trimmed
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: "e" needs to be uppercased to "E"; PAGE:en.w:List_of_countries_and_dependencies_by_population
|
||||
if (expIdx != -1) {
|
||||
valStr = valStr.toUpperCase();
|
||||
}
|
||||
i = -1; // no more trimming needed before decimalPoint; stop looping
|
||||
break;
|
||||
default: // anything else; stop looping
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return valStr;
|
||||
}
|
||||
}
|
||||
|
51
baselib/tst/gplx/objects/primitives/Double_Test.java
Normal file
51
baselib/tst/gplx/objects/primitives/Double_Test.java
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
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.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
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.objects.primitives;
|
||||
|
||||
import gplx.tests.Gftest_fxt;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Double_Test {
|
||||
private final Double_Tstr tstr = new Double_Tstr();
|
||||
|
||||
@Test
|
||||
public void TrimZeroes() {
|
||||
tstr.Test_TrimZeroes("12.100" , "12.1");
|
||||
tstr.Test_TrimZeroes("12.000" , "12");
|
||||
tstr.Test_TrimZeroes("12.001" , "12.001");
|
||||
tstr.Test_TrimZeroes("1020.00" , "1020");
|
||||
tstr.Test_TrimZeroes("1020.00" , "1020");
|
||||
tstr.Test_TrimZeroes("1.200e5" , "1.2E5");
|
||||
tstr.Test_TrimZeroes("1.200e-05" , "1.2E-5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ToStrByPrintF() {
|
||||
tstr.Test_ToStrByPrintF(1d / 2d , "0.5"); // fails with 0.50000000000000
|
||||
tstr.Test_ToStrByPrintF(5d / 100000000000000000d, "5E-17"); // fails with 5.0000000000000e-17
|
||||
tstr.Test_ToStrByPrintF(7538000d / 7773352000d , "0.00096972322879499"); // fails with 0; ISSUE#:697; DATE:2020-08-11
|
||||
tstr.Test_ToStrByPrintF(56225d / 7776747000d , "7.2298867379895E-06"); // fails with 0; ISSUE#:697; DATE:2020-08-11
|
||||
tstr.Test_ToStrByPrintF(35746d / 7805411000d , "4.5796435319037E-06"); // fails with 0; ISSUE#:697; DATE:2020-08-11
|
||||
}
|
||||
}
|
||||
class Double_Tstr {
|
||||
public void Test_ToStrByPrintF(double v, String expd) {
|
||||
Gftest_fxt.Eq__str(expd, Double_.ToStrByPrintF(v));
|
||||
}
|
||||
public void Test_TrimZeroes(String val, String expd) {
|
||||
Gftest_fxt.Eq__str(expd, Double_.TrimZeroes(val));
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user