From af5bf161821a3467ef2e47ce0909a5fb2e6e92ed Mon Sep 17 00:00:00 2001 From: serso Date: Fri, 22 Apr 2016 21:28:26 +0200 Subject: [PATCH] Real should indicate error in parsing --- .../calculator/converter/Converter.java | 15 ++++---- .../converter/ConverterFragment.java | 34 +++++-------------- .../calculator/converter/Convertible.java | 2 +- .../converter/NumeralBaseConvertible.java | 16 +++++---- .../calculator/converter/UnitConvertible.java | 2 +- .../calculator/converter/ConverterTest.java | 18 ++++++++++ jscl/src/main/java/midpcalc/Real.java | 12 +++++-- 7 files changed, 56 insertions(+), 43 deletions(-) create mode 100644 app/src/test/java/org/solovyev/android/calculator/converter/ConverterTest.java diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/Converter.java b/app/src/main/java/org/solovyev/android/calculator/converter/Converter.java index a4835104..bb2dc58d 100644 --- a/app/src/main/java/org/solovyev/android/calculator/converter/Converter.java +++ b/app/src/main/java/org/solovyev/android/calculator/converter/Converter.java @@ -1,7 +1,6 @@ package org.solovyev.android.calculator.converter; import android.support.annotation.NonNull; -import android.text.TextUtils; import android.util.Log; import com.google.common.base.Strings; import jscl.JsclMathEngine; @@ -101,17 +100,21 @@ final class Converter { return 0; } - public static double parse(@NonNull String value) { + @NonNull + public static Real parse(@NonNull String value) throws NumberFormatException { return parse(value, 10); } - public static double parse(@NonNull String value, int base) { + @NonNull + public static Real parse(@NonNull String value, int base) throws NumberFormatException { final String groupingSeparator = String.valueOf(JsclMathEngine.getInstance().getGroupingSeparator()); - if (!TextUtils.isEmpty(groupingSeparator)) { + if (groupingSeparator.length() > 0) { value = value.replace(groupingSeparator, ""); } final Real real = new Real(value, base); - final long bits = real.toDoubleBits(); - return Double.longBitsToDouble(bits); + if (real.isNan()) { + throw new NumberFormatException(); + } + return real; } } diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java b/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java index 42b51dd9..c69ec60b 100644 --- a/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java @@ -21,39 +21,21 @@ import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.ImageButton; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -import org.solovyev.android.calculator.App; -import org.solovyev.android.calculator.AppComponent; -import org.solovyev.android.calculator.AppModule; -import org.solovyev.android.calculator.BaseDialogFragment; -import org.solovyev.android.calculator.Clipboard; -import org.solovyev.android.calculator.Editor; -import org.solovyev.android.calculator.Keyboard; -import org.solovyev.android.calculator.R; +import android.widget.*; +import butterknife.Bind; +import butterknife.ButterKnife; +import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.keyboard.FloatingKeyboard; import org.solovyev.android.calculator.keyboard.FloatingKeyboardWindow; import org.solovyev.android.calculator.keyboard.FloatingNumberKeyboard; import org.solovyev.android.calculator.math.MathUtils; import org.solovyev.android.calculator.view.EditTextCompat; -import java.util.Comparator; - import javax.annotation.Nonnull; import javax.inject.Inject; +import java.util.Comparator; -import butterknife.Bind; -import butterknife.ButterKnife; - -import static org.solovyev.android.calculator.UiPreferences.Converter.lastDimension; -import static org.solovyev.android.calculator.UiPreferences.Converter.lastUnitsFrom; -import static org.solovyev.android.calculator.UiPreferences.Converter.lastUnitsTo; +import static org.solovyev.android.calculator.UiPreferences.Converter.*; public class ConverterFragment extends BaseDialogFragment implements AdapterView.OnItemSelectedListener, View.OnFocusChangeListener, TextView.OnEditorActionListener, View.OnClickListener, TextWatcher { @@ -332,7 +314,7 @@ public class ConverterFragment extends BaseDialogFragment final String value = editTextFrom.getText().toString(); if (TextUtils.isEmpty(value)) { if (validate) { - setError(labelFrom, "Empty"); + setError(labelFrom, R.string.cpp_nan); } return; } @@ -345,7 +327,7 @@ public class ConverterFragment extends BaseDialogFragment } catch (RuntimeException e) { editTextTo.setText(""); if (validate) { - setError(labelFrom, e.getLocalizedMessage()); + setError(labelFrom, R.string.cpp_nan); } } } diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java b/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java index a2ccc9fb..d02017dc 100644 --- a/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java +++ b/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java @@ -5,7 +5,7 @@ import android.support.annotation.NonNull; interface Convertible { @NonNull - String convert(@NonNull Convertible to, @NonNull String value); + String convert(@NonNull Convertible to, @NonNull String value) throws NumberFormatException; @NonNull Named named(@NonNull Context context); diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java index 149b4f65..f211340b 100644 --- a/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java +++ b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java @@ -4,6 +4,7 @@ import android.content.Context; import android.support.annotation.NonNull; import jscl.JsclMathEngine; import jscl.NumeralBase; +import midpcalc.Real; import java.math.BigInteger; @@ -20,15 +21,16 @@ public class NumeralBaseConvertible implements Convertible { @NonNull @Override - public String convert(@NonNull Convertible to, @NonNull String value) { + public String convert(@NonNull Convertible to, @NonNull String value) throws NumberFormatException { final NumeralBase baseTo = ((NumeralBaseConvertible) to).base; - try { - final BigInteger integer = base.toBigInteger(value); - return mathEngine.format(integer, baseTo); - } catch (NumberFormatException e) { - final double d = Converter.parse(value, base.radix); - return mathEngine.format(d, baseTo); + final Real real = Converter.parse(value, base.radix); + if (real.isIntegral()) { + final long l = real.toLong(); + if (l != Long.MAX_VALUE && l != -Long.MAX_VALUE) { + return mathEngine.format(BigInteger.valueOf(l), baseTo); + } } + return mathEngine.format(real.toDouble(), baseTo); } @NonNull diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java b/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java index b14ddb28..e8b3dded 100644 --- a/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java +++ b/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java @@ -34,7 +34,7 @@ final class UnitConvertible implements Convertible { @NonNull @Override public String convert(@NonNull Convertible to, @NonNull String value) { - final double from = Converter.parse(value); + final double from = Converter.parse(value).toDouble(); final double converted = unit.getConverterTo(((UnitConvertible) to).unit).convert(from); return format(converted); } diff --git a/app/src/test/java/org/solovyev/android/calculator/converter/ConverterTest.java b/app/src/test/java/org/solovyev/android/calculator/converter/ConverterTest.java new file mode 100644 index 00000000..c714d0b9 --- /dev/null +++ b/app/src/test/java/org/solovyev/android/calculator/converter/ConverterTest.java @@ -0,0 +1,18 @@ +package org.solovyev.android.calculator.converter; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ConverterTest { + + @Test(expected = NumberFormatException.class) + public void testShouldNotParseInvalidDecNumber() throws Exception { + Converter.parse("1A", 10); + } + + @Test + public void testShouldParseValidHexNumber() throws Exception { + assertEquals(26, Converter.parse("1A", 16).toLong()); + } +} \ No newline at end of file diff --git a/jscl/src/main/java/midpcalc/Real.java b/jscl/src/main/java/midpcalc/Real.java index d42294fe..572cc862 100755 --- a/jscl/src/main/java/midpcalc/Real.java +++ b/jscl/src/main/java/midpcalc/Real.java @@ -771,8 +771,8 @@ public final class Real { *     base-16: "/FFF800C.CCCE e64" *

*

The number is parsed until the end of the string or an unknown - * character is encountered, then silently returns even if the whole - * string has not been parsed. Please note that specifying an + * character is encountered. Note that in case of latter this Real becomes + * NAN. Please note that specifying an * excessive number of digits in base-10 may in fact decrease the * accuracy of the result because of the extra multiplications performed. *

@@ -2243,6 +2243,10 @@ public final class Real { return (this.sign == 0) ? (mantissa >>> shift) : -(mantissa >>> shift); } + public double toDouble() { + return Double.longBitsToDouble(toDoubleBits()); + } + /** * Returns true if the value of this Real * represents a mathematical integer. If the value is too large to @@ -6184,6 +6188,10 @@ public final class Real { } } sign = tmpSign; + if (index != length) { + // signal error + assign(NAN); + } } //*************************************************************************