Программа уравнений — ошибка, похоже, указывает на неправильную строку

#java #android

#java #Android

Вопрос:

Я создаю приложение, в котором пользователь вводит от 7 до 10 числовых значений в нескольких действиях. Затем записи используются в довольно многоуровневом уравнении, которое возвращает результат пользователю. Два значения доставляют мне проблемы и создают NumberFormatException то, что я не могу понять.

Одна запись IHCValue выбирается из счетчика, поскольку существует только 4 возможных варианта:

 <string-array name="ihc_choices">
    <item>0</item>
    <item>1</item>
    <item>2</item>
    <item>3</item>
</string-array>
  

Этот выбор не только используется в уравнении, но и определяет, требуется ли дополнительная информация.

Получение значения IHCValue:

    private void directSpinner(){

        int spinnerPosition = scoreSelect.getSelectedItemPosition();
        String[] IHC_Values = getResources().getStringArray(R.array.ihc_choices);
        String IHCValue = String.valueOf(IHC_Values[spinnerPosition]);
        SharedPrefManager.write(IHC_VALUE, IHCValue);

        //The string to manage Intent defined separately as the intent did not recognize the value of 'String IHCValue'
        String IHCEntry = scoreSelect.getSelectedItem().toString();
        if (IHCEntry.equals("2")){
            //Status equivocal, must collect more information before calculation can be performed.
            Intent next = new Intent(getApplicationContext(), FishScoreActivity.class);
            startActivity(next);
        } else { //IHCValue of 0,1,3
            //Status is defined, we have enough info to perform calculation.
            Intent last = new Intent(getApplicationContext(), CancerDemographicActivity.class);
            startActivity(last);
        }
    }
  

Если пользователь выбирает «2» из этого выпадающего списка, запрашивается следующее действие FISHEntry , также используемое в части уравнения:

Получение FISHEntry:

 public boolean validateData(){
    boolean validData = false;

    String FISHEntry = enterFISH.getText().toString();

    if (!FISHEntry.equals("")){
        SharedPrefManager.write(FISH_RATIO, FISHEntry);
        validData = true;
    } else {
        Toast.makeText(getApplicationContext(), "Please enter FISH ratio from your report.", Toast.LENGTH_LONG).show();
        validData = false;
    }
    return validData;
}
  

Затем пользователь может нажать кнопку и запустить уравнение. Если пользователь выбрал IHCValue значение 0,1 или 3 FISHEntry , оно не требуется, и уравнение выполняется нормально.

Если (и только если), IHCValue = 2 то в классе Equation необходимо выполнить дополнительное вычисление, что приведет к сбою приложения.

Шаги, которые я выполнил из приложения:

  1. Из счетчика IHCValue выбрано значение 2.
  2. Предлагается ввести оценку РЫБЫ, FISHEntry = 2.3
  3. Нажмите кнопку «Рассчитать»:

Затем приложение выходит из строя:

 Caused by: java.lang.NumberFormatException: Invalid int: "2.3"
    at java.lang.Integer.invalidInt(Integer.java:138)
    at java.lang.Integer.parse(Integer.java:410)
    at java.lang.Integer.parseInt(Integer.java:367)
    at java.lang.Integer.parseInt(Integer.java:334)
    at com.them.health.Equations.MasterEquation.<clinit> 
(MasterEquation.java:42)
  

«2.3» — это моя FISHEntry строка while 42, которая объявляет IHCValue :

MasterEquation.java:42

 private static int mIHCValue = Integer.parseInt(SharedPrefManager.read(IHC_VALUE, null));
  

FISHEntry is declared on MasterEquation.java:41:

 private static double mFISHRatio = Double.valueOf(SharedPrefManager.read(FISH_RATIO, null));
  

To be consistent, all values are saved to SharedPrefs as string and I parse int or double as needed when the equation is performed. Also, I received a String-to-Integer error when saving the IHCValue directly as an int.

Method in MasterEquation.java which uses the variables:

 private void calcRatioOne(){

    double innerRatio = mIHCValue/mFISHRatio;

    if (mIHCValue == 0 || mIHCValue == 1){
        mRatioOne = 0.0;

    } else if (mIHCValue == 3){
        mRatioOne = 12.75525;

    } else if (mIHCValue == 2){ //IHC = 2 takes FISHEntry into account.

        if (innerRatio >= 2.2){
            mRatioOne = 12.75525;
        }
        if (innerRatio >= 1.8){
            mRatioOne = 1.46495;

        }
        if (innerRatio < 1.8){
            mRatioOne = 0.0;

        }
    }
}
  

private double mRatioOne; определяется в начале.

Я попробовал следующее:

  1. Записывайте значения в SharedPrefs как int / float, когда пользователь вводит их. Ошибка преобразования в double при запуске equation.
  2. Создан метод специально для обработки innerRatio вычислений. Та же проблема.
  3. Объявляйте и обрабатывайте значение IHCValue как double / float . Та же проблема.
  4. Объявлено IHCValue как Integer вместо int . Та же проблема.

Это проблема только тогда, когда IHCValue = 2

Я не против изменения записи IHC с счетчика на другой метод ввода, если это поможет, но хотел бы избежать свободного текста, поскольку это самая важная запись в последовательности.

Мой SharedPrefManager:

Объявленный ключ:

 public static final String IHC_VALUE = null;
  

Метод чтения и записи:

 public static String read(String key, String defValue){
    return userPrefs.getString(key, defValue);
}

public static void write(String key, String value) {
    SharedPreferences.Editor prefsEditor = userPrefs.edit();
    prefsEditor.putString(key, value);
    prefsEditor.commit();
}
  

Комментарии:

1. Вы пробовали запускать ее с помощью отладчика?

2. Хотя это довольно просто: Caused by: java.lang.NumberFormatException: Invalid int: "2.3" пожалуйста, измените

3. @Shark Я ценю ответ. Сначала я не был уверен, с чего начать вопрос — отсутствие опыта отладки этому не помогло. Я провел все это утро, изучая отладчик. ВАУ! Удивительно полезно и проницательно. Я могу сказать, что это уже уменьшит количество вопросов, которые мне нужно задать здесь и моим друзьям.

4. @Shark Я краду твою цитату :)! Просто дополнение здесь: используйте IDE для написания кода. Всегда. Это значительно упрощает обнаружение ошибок и разработку хорошего, качественного кода. Моим личным фаворитом и в целом популярной IDE является IntelliJ . Существует бесплатная версия, но если вы студент, вам разрешено бесплатно использовать конечную версию. Инструмент отладчика этой IDE прост в освоении, а также очень хорош. (То, что Shark раньше называл отладчиком, на самом деле является компилятором JVM, выдающим сообщение об ошибке)

5. @P.Soutzikevich Спасибо! Я все делаю в Android Studio, но не был настолько блаженным, не зная об инструменте отладки. Абсолютно поразило меня — до этого у меня была деятельность, целью которой было присвоить моим переменным EditText, чтобы убедиться, что они верны, очень подход Рубе Голдберга.

Ответ №1:

Из сообщения об ошибке очевидно, в чем проблема. Вы пытаетесь присвоить значение «2.3» переменной целочисленного типа.

Лучшим решением было бы использовать инструмент отладчика, предлагаемый в большинстве интегрированных сред разработки (IDE), таких как IntelliJ или Eclipse. С помощью этого инструмента отладчика выясните, почему изначально присвоено неправильное значение IHCValue , и действуйте соответствующим образом, чтобы устранить ошибку.

Я не согласен с исправлением, предложенным в комментариях @shark; назначение a Float для an int является несовместимой операцией. Мое предложение — изменить тип mIHCValue на double .

Если mIHCValue должно быть целым числом, затем преобразуйте его из строки в double, а затем преобразуйте как целое число. Вот так:

 private double originalIHC = Double.valueOf(SharedPrefManager.read(IHC_VALUE, null));
private static int mIHCValue = (int) originalIHC;
  

Позвольте мне объяснить, почему я сделал это в 2 строках. Поскольку значение строки является не целым числом, а числом с плавающей запятой, мы должны сначала проанализировать его как double . Но преобразовать строку в примитив double невозможно, поэтому мы должны использовать класс-оболочку Double для этого.

Класс-оболочка Double (бокс) несовместим с примитивным типом, отличным от double , поэтому мы сначала присваиваем «обернутое» значение его примитиву.

После преобразования начального значения в примитив double мы можем преобразовать его в целое число, как показано на рисунке.

Обратите внимание, что это решение поможет вам получить только целую часть любого числа с плавающей запятой. Например, если значение mIHCValue равно 2.8 или 2.0012 или 2.532 или 2.9999999 , результирующее целое число всегда будет 2 . Итак, будьте осторожны и подумайте о том, чего вы хотите достичь.

Надеюсь, это поможет.

Комментарии:

1. или запретить ввод "2.3" , если оно должно быть целым числом; решение действительно зависит от требований проекта. но я согласен; ваше решение лучше 🙂

2. @shark Да, точно! Но просто для справки, это решение не просто лучше; операция, которую вы предложили в комментариях, даже не будет компилироваться. Вы не можете назначить a Float для an int .

3. @P.Soutzikevich Я попробую это сейчас, однако "2.3" вводится для значения FISH (которое является двойным), а не для значения IHC (int). Logcat показывает, что проблема связана со значением IHC, которое может быть только целым значением 0-3.

4. @SentientFlesh Если «предполагается» , что это int , то проблема может быть вызвана методом SharedPrefManager.read()

5. @P.Soutzikevich Хорошо, на данный момент не могу попробовать ваш ответ, но я обновил вопрос с помощью методов SharedPref на случай, если это что-то есть. Надеюсь, это сработает! Спасибо за быструю обратную связь.