Вторник, 20.11.2018, 18:33
Поиск
Никнэйм
Сертификат на никнейм Olelucoye, зарегистрирован на Тимофеев Константин Михайлович
Зарегистрируй свой никнейм
Обратная связь
olelucoye.tk@yandex.ru
Реклама AdSense
Реклама
Друзья сайта
  • Лига медицинского права
  • Гостиница "Зай"
  • FAQ по системе
  • Инструкции для uCoz
  • Главная » Статьи » Андроид разработка

    Программируем калькулятор на андроид. Урок 7.

    Урок сделан специально для группы http://vk.com/amdroid.developer

    Урок 7. Обработка чисел с запятой.

    Преамбула к уроку:  Когда я начал писать код для этого урока, я решил хранить  целую и дробную часть вводимого числа в одной переменной типа double, программно ограничив количество разрядов, которые можно ввести.  Дробная часть вводится по формуле: предыдущее значение + нажатая цифра / 10 в степени равном вводимому разряду. Все вроде правильно, но периодически при вводе появлялись значения вроде XXX.YYY000000001 или XXX.YYY99999999. Дело в том, компьютер оперирует числами в двоичном представлении и, в общем , это нормальный результат для двоичной математики.  Порывшись в инете, я выяснил, что другие языки программирования сглаживают результат до правильного значения, а Java, как самый честный в мире язык, показывает всю подноготную. "Сейчас округлим" - подумал я. Но не тут то было. В Java нет библиотечной функции для округления дробного числа до определенного разряда после запятой, можно округлить только до целого числа. Правильно было бы изменить подход к задаче - хранить целую и дробную часть числа в разных целочисленных переменных, но я решил пойти до конца, округляя числа с помощью математических вычислений и посмотреть, что получится. Пришлось вводить много проверок и вычислений. Я почти добился правильного отображения чисел (немного неудобно для восприятия отображается число при удалении последнего введенного символа), но код стал несколько запутан. Переделывать код не хочется, чтобы не задерживать выход следующего урока, поэтому приведу код в таком виде как есть сейчас. Но если вы собираетесь выпустить приложение в свет, код нужно подвергнуть тщательной коррекции, а лучше переделать и хранить дробную часть операндов отдельно от целой.

    Итак, три новых константы в string.xml и полный код MainActivity.java

    Весь новый код раскомментировал, поэтому объяснений не пишу.

    string.xml

    <string name="limit_before">Ограничение разрядности = 8</string>

    <string name="limit_after">Ограничение знаков после запятой = 2</string>

    <string name="degree_overflow">Ошибка: переполнение разрядности.</string>

    MainActivity.java

    package ru.urok.super_calc;

     

    import android.app.Activity;

    import android.content.Intent;

    import android.content.SharedPreferences;

    import android.os.Bundle;

    import android.preference.PreferenceManager;

    import android.view.Menu;

    import android.view.MenuItem;

    import android.view.View;

    import android.view.View.OnClickListener;

    import android.widget.Button;

    import android.widget.LinearLayout;

    import android.widget.TextView;

    import android.widget.Toast;

     

    public class MainActivity extends Activity implements OnClickListener {

           Button btOne, btTwo, btThree, btFour, btFive;

           Button btSix, btSeven, btEight, btNine, btZero;

           Button btPlus, btMinus, btMulti, btDiv, btEqual, btClear;

           Button btPoint, btSquare, btRadical, btBack;

           TextView tvLCD;

           double operand1, operand2;

           int flagAction;

           double result;

           SharedPreferences sp;

           Boolean add_button;

           String style_calc;

           LinearLayout llExtra;

           int[] bt_ids;

           Button[] bt_array;

           int len;

           //флаг нажатия точки

           Boolean flagPoint;

           //счетчики разрядов до запятой и после

           int degree_before, degree_after;

     

           @Override

           protected void onCreate(Bundle savedInstanceState) {

                 super.onCreate(savedInstanceState);

                 setContentView(R.layout.activity_main);

                 sp = PreferenceManager.getDefaultSharedPreferences(this);

                 tvLCD = (TextView) findViewById(R.id.tvLCD);

                 llExtra = (LinearLayout) findViewById(R.id.llExtra);

                 bt_ids = new int[]{R.id.btOne, R.id.btTwo, R.id.btThree,                                            R.id.btFour,

                               R.id.btFive, R.id.btSix, R.id.btSeven, R.id.btEight,

                               R.id.btNine, R.id.btZero, R.id.btPlus, R.id.btMinus,

                               R.id.btMulti, R.id.btDiv, R.id.btEqual, R.id.btClear,

                               R.id.btPoint, R.id.btSquare, R.id.btRadical, R.id.btBack};

                 bt_array = new Button[]{btOne, btTwo, btThree, btFour, btFive,                                 btSix,

                               btSeven, btEight, btNine,btZero, btPlus, btMinus, btMulti,

                               btDiv, btEqual, btClear, btPoint, btSquare, btRadical,                                  btBack};

                 len = bt_array.length;

                 for(int i = 0; i < len; i++){

                        bt_array[i] = (Button) findViewById(bt_ids[i]);

                        bt_array[i].setOnClickListener(this);

                 }

                 clearVariables();

                 showNumber(operand1);

           }

          

           protected void onResume() {

               add_button = sp.getBoolean("add_button", false);

               style_calc = sp.getString("style_calc", "1");

               int flag_visiblity = View.INVISIBLE;

               if(add_button)flag_visiblity = View.VISIBLE;

               llExtra.setVisibility(flag_visiblity);

               super.onResume();

             }

     

           @Override

           public boolean onCreateOptionsMenu(Menu menu) {

                 getMenuInflater().inflate(R.menu.main, menu);

                 return true;

           }

     

           @Override

           public boolean onOptionsItemSelected(MenuItem item) {

                 switch(item.getItemId()){

                 case R.id.options_menu:

                        startActivity(new Intent(this, PrefActivity.class));

                        break;

                 case R.id.about_menu:

                        startActivity(new Intent(this, AboutActivity.class));

                        break;

                 }

                 return super.onOptionsItemSelected(item);

           }

     

           @Override

           public void onClick(View v) {

                 switch(v.getId()){

                 case R.id.btOne:

                        ClickNumber(1);

                        break;

                 case R.id.btTwo:

                        ClickNumber(2);

                        break;

                 case R.id.btThree:

                        ClickNumber(3);

                        break;

                 case R.id.btFour:

                        ClickNumber(4);

                        break;

                 case R.id.btFive:

                        ClickNumber(5);

                        break;

                 case R.id.btSix:

                        ClickNumber(6);

                        break;

                 case R.id.btSeven:

                        ClickNumber(7);

                        break;

                 case R.id.btEight:

                        ClickNumber(8);

                        break;

                 case R.id.btNine:

                        ClickNumber(9);

                        break;

                 case R.id.btZero:

                        ClickNumber(0);

                        break;

                 case R.id.btPlus:

                        if(flagAction == 0){

                               flagAction = 1;

                               //обнуляем счетчики и флаг точки

                               clearDegree();

                        }

                        break;

                 case R.id.btMinus:

                        if(flagAction == 0){

                               flagAction = 2;

                               //обнуляем счетчики и флаг точки

                               clearDegree();

                        }

                        break;

                 case R.id.btMulti:

                        if(flagAction == 0){

                               flagAction = 3;

                               //обнуляем счетчики и флаг точки

                               clearDegree();

                        }

                        break;

                 case R.id.btDiv:

                        if(flagAction == 0){

                               flagAction = 4;

                               //обнуляем счетчики и флаг точки

                               clearDegree();

                        }

                        break;

                 case R.id.btPoint:

                        //здесь просто меняем значение флага на true

                        flagPoint = true;

                        break;

                 case R.id.btSquare:

                        if(flagAction == 0){

                               result = Math.pow(operand1, 2);

                               //если результат не целый устанавливаем стчетчик после запятой = 2

                               if(result%1 != 0)degree_after = 2;

                               showNumber(result);

                               clearVariables();

                        }else{

                               Toast.makeText(this, R.string.other_operation, Toast.LENGTH_LONG).show();

                        }

                        break;

                 case R.id.btRadical:

                        if(flagAction == 0){

                               result = Math.sqrt(operand1);

                               //если результат не целый устанавливаем стчетчик после запятой = 2

                               if(result%1 != 0)degree_after = 2;

                               showNumber(result);

                               clearVariables();

                        }else{

                               Toast.makeText(this, R.string.other_operation, Toast.LENGTH_LONG).show();

                        }

                        break;

                 case R.id.btBack:

                        String Temp;

                        if(flagAction == 0){

                               //проверяем не введен ли после запятой ноль

                               if(operand1%1 == 0 & degree_after == 0){

                                      Temp = Integer.toString((int)operand1);

                               }else{Temp = Double.toString(operand1);}

                               Temp = Temp.substring(0, Temp.length()-1);

                               if(Temp.length() > 0){

                               operand1 = Double.parseDouble(Temp);

                               }else{operand1 = 0;}

                               showNumber(operand1);

                        }else{

                               //проверяем не введен ли после запятой ноль

                               if(operand2%1 == 0 & degree_after == 0){

                                      Temp = Integer.toString((int)operand2);

                               }else{Temp = Double.toString(operand2);}

                               Temp = Temp.substring(0, Temp.length()-1);

                               if(Temp.length() > 0){

                                      operand2 = Double.parseDouble(Temp);

                               }else{operand2 = 0;}

                               showNumber(operand2);

                        }

                        //если счетчик после запятой больше 0, уменьшаем на 1

                        //если равен 0, флаг точки ставим false

                        if(degree_after > 0){

                               degree_after--;

                        }else{

                               flagPoint = false;}

                        break;

                 case R.id.btEqual:

                        switch(flagAction){

                               case 1:

                                      result = operand1 + operand2;

                                      break;

                               case 2:

                                      result = operand1 - operand2;

                                      break;

                               case 3:

                                      result = operand1 * operand2;

                                      break;

                               case 4:

                                      result = operand1 / operand2;

                                      break;

                               default:

                                      Toast.makeText(this, R.string.no_operation, Toast.LENGTH_LONG).show();

                        }

                        //если результат не целый устанавливаем счетчик после запятой = 2

                        if(result%1 != 0)degree_after = 2;

                        if(flagAction != 0){

                               showNumber(result);

                               clearVariables();

                        }

                        break;

                 case R.id.btClear:

                        clearVariables();

                        showNumber(operand1);

                        break;

                 }

           }

          

           private void ClickNumber(int num){

                 if(flagAction == 0){

                        //проверяем флаг точки, т.е вводим целую или дробную часть

                        if(flagPoint){

                               //увеличиваем счетчик после точки на 1

                               //проверяем ограничение разрядности

                               //если превышена - сообщение, если нет добавляем к операнду цифру

                               degree_after++;

                               if(degree_after <= 2){

                                      operand1 += num / Math.pow(10, degree_after);

                               }else{

                                      degree_after = 2;

                                      Toast.makeText(this, R.string.limit_after, Toast.LENGTH_LONG).show();

                               }

                        }else{

                               //увеличиваем счетчик до точки на 1

                               //проверяем ограничение разрядности

                               //если превышена - сообщение, если нет добавляем к операнду цифру

                               degree_before++;

                               if(degree_before <= 8){

                               operand1 = operand1*10 + num;

                               }else{

                                      degree_before = 8;

                                      Toast.makeText(this, R.string.limit_before, Toast.LENGTH_LONG).show();

                               }

                        }

                        showNumber(operand1);

                 }else{

                        //проверяем флаг точки, т.е вводим целую или дробную часть

                        if(flagPoint){

                               //увеличиваем счетчик после точки на 1

                               //проверяем ограничение разрядности

                               //если превышена - сообщение, если нет добавляем к операнду цифру

                               degree_after++;

                               if(degree_after <= 2){

                                      operand2 += num / Math.pow(10, degree_after);

                               }else{

                                      degree_after = 2;

                                      Toast.makeText(this, R.string.limit_after, Toast.LENGTH_SHORT).show();

                               }

                        }else{

                               //увеличиваем счетчик до точки на 1

                               //проверяем ограничение разрядности

                               //если превышена - сообщение, если нет добавляем к операнду цифру

                               degree_before++;

                               if(degree_before <= 8){

                               operand2 = operand2*10 + num;

                               }else{

                                      degree_before = 8;

                                      Toast.makeText(this, R.string.limit_before, Toast.LENGTH_SHORT).show();

                               }

                        }

                        showNumber(operand2);

                 }

           }

          

           private void showNumber(double num){

                 //корректирующая переменная

                 String corr = "";

                 //проверяем не превышает ли значение num

                 //максимального значения int

                 //если превышает - сообщение о переполнении разрядности

                 if(num > Integer.MAX_VALUE){

                        tvLCD.setText("ERROR");

                        Toast.makeText(this, R.string.degree_overflow, Toast.LENGTH_LONG).show();

                 }else{

                 //проверяем целое число или дробное

                 if(num%1 == 0 & degree_after == 0){

                        tvLCD.setText(Integer.toString((int) num));

                 }else{

                        //если дробное отделяем целую и дробную часть

                        int part_int = (int) num;

                        int part_frac = (int) Math.round(num%1 * Math.pow(10, degree_after));

                        //если счетчик после запятой = 2

                        //а дробная часть занимает только один разряд

                        //значит есть только сотые доли числа, десятых нет

                        //присваиваем корректирующей переменной значение 0

                        if(degree_after == 2 & part_frac < 10)corr = "0";

                        tvLCD.setText(part_int + "." + corr + part_frac);

                        }

                 }

           }

           private void clearVariables(){

                 operand1 = 0;

                 operand2 = 0;

                 result = 0;

                 flagAction = 0;

                  clearDegree();

           }

           //метод обнуляет счетчики и флаг точки

           private void clearDegree(){

                 degree_before = 0;

                 degree_after = 0;

                 flagPoint = false;

           }

    }

    Программируем калькулятор на андроид. Урок 10.

    Программируем калькулятор на андроид. Урок 9.

    Программируем калькулятор на андроид. Урок 8.

    Программируем калькулятор на андроид. Урок 6.

    Программируем калькулятор на андроид. Урок 5.

    Программируем калькулятор на андроид. Урок 4.

    Программируем калькулятор на андроид. Урок 3.

    Программируем калькулятор на андроид. Урок 2.

    Программируем калькулятор на андроид. Урок 1.

    Категория: Андроид разработка | Добавил: Olelucoye (29.11.2014)
    Просмотров: 3049
    | Теги: Калькулятор, java, Android, числа с запятой | Рейтинг: 0.0/0
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]
    Меню сайта
    Категории раздела
    Андроид разработка [23]
    libGDX [24]
    Мои андроид проекты [6]
    Excel [7]
    Железяки [5]
    Скрипты в блокноте [4]
    Разное [1]
    Форма входа
    Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0
    Яндекс Метрика
    Яндекс.Метрика