Android calculator 默认计算器 计算错误 bug fix
Android calculator 默认计算器 计算错误 bug fix
Android默认的计算器计算错误 : 5.04-4.99= 0.0499999
其实这是一个正常的结果,其产生的原因就是:
计算机计算时使用的是2进制,而我们输入的是10进制。10进制的小数转2进制就有可能产生精度丢失的问题.
Android这个calculator采用的是arity框架封装的,而arity并没有正确处理这些精度问题。
下面算是个workaround,代码不好请多见谅。
- Index: src/com/android/calculator2/Logic.java
- ===================================================================
- --- src/com/android/calculator2/Logic.java (revision 600)
- +++ src/com/android/calculator2/Logic.java (revision 604)
- +
- + /**
- + * function to truncate decimal
- + * @author jacky yang
- + *
- + * @param number
- + * @param length
- + * @return the exact number in decimal
- + */
- + private String getPrecisionNumber(double number, int length) {
- +
- + //1.get formatted string from double
- + String formatString = new String("%"+mLineLength+"."+length+"g");
- + String value = String.format(Locale.US, formatString, Double.valueOf(number)).trim();
- + if(DBG) Log.d(TAG, "value="+value+"\nnumber="+number+"\nlength="+length);
- + //2.if it's NaN 00 -00, just return string
- + if(NAN.equals(value)||INFINITY.equals(value)||("-"+INFINITY).equals(value)) {
- + mIsError = true;
- + return mErrorString;
- + }
- + //3.split science value to two part
- + int indexOfE = value.indexOf('e');
- + String prePart = null;
- + String postPart = null;
- + if(indexOfE != -1) {
- + prePart = value.substring(0, indexOfE);
- + postPart = value.substring(indexOfE+1);
- + if(postPart.startsWith("+")) {
- + postPart = postPart.substring(1);
- + }
- + if(DBG) Log.d(TAG, "pre : "+ prePart +" back : "+ postPart);
- + } else {
- + prePart = value;
- + }
- + //4.round the decimal in the prePart
- + while (true) {
- + int m = prePart.indexOf('.');
- + if(m == -1) {
- + m = prePart.indexOf(',');
- + if(m == -1) {
- + break;
- + }
- + }
- + while(true) {
- + if(prePart.length()>0 && prePart.endsWith("0")) {
- + prePart = prePart.substring(0, prePart.length()-1);
- + continue;
- + } else {
- + break;
- + }
- + }
- + if((m+1) != prePart.length()) {
- + break;
- + } else {
- + prePart = prePart.substring(0, prePart.length()-1);
- + }
- +
- + }
- + //5.append the postPart
- + if(postPart != null) {
- + prePart = prePart + "E" + postPart;
- + }
- + return prePart;
- + }
- +
- +// private static final int ROUND_DIGITS = 1; commented by jacky.yang 2011.08.26
- String evaluate(String input) throws SyntaxException {
- if (input.trim().equals("")) {
- return "";
- @@ -181,18 +255,33 @@
- input = input.substring(0, size - 1);
- --size;
- }
- -
- - String result = Util.doubleToString(mSymbols.eval(input), mLineLength, ROUND_DIGITS);
- - if (result.equals(NAN)) { // treat NaN as Error
- - mIsError = true;
- - return mErrorString;
- - } else if (result.equals(INFINITY)) {// add by pxy
- - mIsError = true;
- - return mErrorString;
- - } else if (result.equals('-' + INFINITY)) {// add by pxy
- - mIsError = true;
- - return mErrorString;
- - }
- + //added by jacky.yang 2011.08.26
- + String result = "";
- + double d = mSymbols.eval(input);
- + int m = mLineLength;
- + while(true) {
- + if(m>6) {
- + result = getPrecisionNumber(d, m);
- + if(DBG) Log.d(TAG, result);
- + } else {
- + break;
- + }
- + m--;
- + }//end
- +
- + /* commented by jacky yang 2011.08.26
- +// String result = Util.doubleToString(mSymbols.eval(input), mLineLength, ROUND_DIGITS);
- +// if (result.equals(NAN)) { // treat NaN as Error
- +// mIsError = true;
- +// return mErrorString;
- +// } else if (result.equals(INFINITY)) {// add by pxy
- +// mIsError = true;
- +// return mErrorString;
- +// } else if (result.equals('-' + INFINITY)) {// add by pxy
- +// mIsError = true;
- +// return mErrorString;
- +// }
- + */
- //modify by pxy
- // return result.replace('-', MINUS).replace(INFINITY, INFINITY_UNICODE);
- return result.replace('-', MINUS);
评论暂时关闭