Страницы

Поиск по вопросам

среда, 29 января 2020 г.

Деление в столбик на Java

#java #деление #большие_числа


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



Мой код:

public class LongDivUtil {
    private String result = "";
    private int remDiv = 0;
    private int quotient;
    private int dividend;
    private int divider;
    private int[] numbersDividend;
    private String[] numbersOfDividendInStrVal;

    public LongDivUtil(int dividend, int divider) {
        this.dividend = dividend;
        this.divider = divider;
        this.numbersOfDividendInStrVal = (dividend + "").split("");
        this.numbersDividend = new int[numbersOfDividendInStrVal.length];
        for (int i = 0; i < numbersOfDividendInStrVal.length; i ++){
            numbersDividend[i] = Integer.parseInt(numbersOfDividendInStrVal[i]);
        }
    }

    public void executeDivision(){
        System.out.println("execute");
        System.out.println(this.dividend + "|" + this.divider);
        /////////////////////////////////////////////////////////////////
        int tmpInt = numbersDividend[0];
        boolean  isContinue = false;
        for (int i = 0; i < numbersOfDividendInStrVal.length || isContinue; i++) {
            if (tmpInt >= divider) {
                quotient = tmpInt / divider;
                result += quotient;
                remDiv = tmpInt % divider;
                isContinue = false;
                System.out.println("result = " + result);////////////////
                System.out.println("remDiv = " + remDiv);//////////////
                if (remDiv != 0 && i != numbersOfDividendInStrVal.length - 1){//1
                    tmpInt = Integer.parseInt((remDiv + "") + (numbersDividend[i] + ""));
                    System.out.println(tmpInt);
                    continue;
                }
                if (i < numbersOfDividendInStrVal.length -1){//2
                    tmpInt = numbersDividend[++i];
                    isContinue = true;
                }
                continue;
            } else {
                if (tmpInt == 0){//4
                    result += tmpInt;
                    if (i < numbersOfDividendInStrVal.length){
                        tmpInt = i;
                    }
                    isContinue = false;
                    continue;
                }
                if (tmpInt < divider){
                    tmpInt = Integer.parseInt(numbersOfDividendInStrVal[i] + numbersOfDividendInStrVal[++i]);
                    isContinue = true;
                    continue;
                }
            }
        }
        /////////////////////////////////////////////////////////////
        System.out.println("out");
    }
}


В нете, часто встречающийся вопрос, но ничего не находил в рекомендациях. Пока пишу
сам, но получается, мягко говоря, не очень. Кто ни будь сталкивался с подобным? 
    


Ответы

Ответ 1



Код стоит подправить, но представленный пример показывает основные принципы, которые необходимо реализовать. public class LongDivUtil { private int dividend; private int divider; private int n; private StringBuffer dividendSB; private StringBuffer result=new StringBuffer(""); private StringBuffer firstSplitedString; private StringBuffer secondSplitedString; private StringBuffer print=new StringBuffer(""); public LongDivUtil(int dividend, int divider) { this.dividend = dividend; this.divider = divider; result=new StringBuffer(""); this.dividendSB=new StringBuffer(Integer.toString(this.dividend)); } public void printSomeCharSomeTimes(String s,int n){ for (int i = 0; i =this.divider;i++){ print.append("\n"+t.toString()+this.getLeftDividendNumber()); count(); print.append("\n"+t.toString()+n*divider); t.append(" "); } if (this.dividend!=0) result.append("."); int numberOfDigits=5; while(this.dividend!=0&&numberOfDigits!=0){ for (int i =0;dividend0){ result.append("0"); } } count(); numberOfDigits--; } return result; } public int getLeftDividendNumber(){ int i=1; while (Integer.parseInt(Integer.toString(this.dividend).substring(0, i))

Ответ 2



Смысл в том что в классе сначала реализуется конвейер деления. Каждый этап добавляется в строку результата. Потом сторка модифициреутся для отображения красивого деления в столбик. На входе главного метода два числа(делимое и делитель), на выходе получаем строку - полную отрисовку деления в столбик. Метод легко тестируется. public class Division { private StringBuilder result = new StringBuilder(); private StringBuilder quotient = new StringBuilder(); private StringBuilder reminder= new StringBuilder(); public String makeDivision(int dividend, int divisor) { if (divisor == 0) { throw new IllegalArgumentException("Divisor cannot be 0, division by zero"); } dividend = Math.abs(dividend); divisor = Math.abs(divisor); if (dividend < divisor) { return "" + dividend + "/" + divisor + "=0"; } String[] digits = String.valueOf(dividend).split(""); Integer reminderNumber; Integer multiplyResult; Integer divisorDigit = calculateDigit(divisor); Integer mod; for (int i = 0; i < digits.length; i++) { reminder.append(digits[i]); reminderNumber = Integer.parseInt(reminder.toString()); if (reminderNumber >= divisor) { mod = reminderNumber % divisor; multiplyResult = reminderNumber / divisor * divisor; String lastReminder = String.format("%" + (i + 2) + "s", "_" + reminderNumber.toString()); result.append(lastReminder).append("\n"); String multiply = String.format("%" + (i + 2) + "d", multiplyResult); result.append(multiply).append("\n"); Integer tab = lastReminder.length() - calculateDigit(multiplyResult); result.append(makeDivider(reminderNumber, tab)).append("\n"); quotient.append(reminderNumber / divisor); reminder.replace(0, reminder.length(), mod.toString()); reminderNumber = Integer.parseInt(reminder.toString()); } else { if (i >= divisorDigit) { quotient.append(0); } } if (i == digits.length - 1) { result.append(String.format("%" + (i + 2) + "s", reminderNumber.toString())).append("\n"); } } modifyResultToView(dividend, divisor); return result.toString(); } private String makeDivider(Integer reminderNumber, Integer tab) { return assemblyString(tab, ' ') + assemblyString(calculateDigit(reminderNumber), '-'); } private void modifyResultToView(Integer dividend, Integer divisor) { int[] index = new int[3]; for (int i = 0, j = 0; i < result.length(); i++) { if (result.charAt(i) == '\n') { index[j] = i; j++; } if (j == 3) { break; } } int tab = calculateDigit(dividend) + 1 - index[0]; result.insert(index[2], assemblyString(tab, ' ') +"│" + quotient.toString()); result.insert(index[1], assemblyString(tab, ' ') +"│" + assemblyString(quotient.length(), '-')); result.insert(index[0], "│" + divisor); result.replace(1, index[0], dividend.toString()); } private int calculateDigit(int i) { return (int) Math.log10(i) + 1; } private String assemblyString(int numberOfSymbols, char symbol) { StringBuilder string = new StringBuilder(); for (int i = 0; i < numberOfSymbols; i++) { string.append(symbol); } return string.toString(); } } пример результата: _10210│5 10 │---- -- │2042 _21 20 -- _10 10 -- 0 Пример теста: Division division = new Division(); @Test public void shouldMakeDivision() { String expected = "_14789│20\n" + " 140 │---\n" + " --- │739\n" + " _78\n" + " 60\n" + " --\n" + " _189\n" + " 180\n" + " ---\n" + " 9\n"; assertEquals(expected, division.makeDivision(14789, 20)); }

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

Отправить комментарий