Страницы

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

Показаны сообщения с ярлыком деление. Показать все сообщения
Показаны сообщения с ярлыком деление. Показать все сообщения

среда, 12 февраля 2020 г.

Деление заменить смещением(сдвигом)

#математика #деление


int b=(a<<6)+(a<<5)+(a<<2);//умножить на 100
int c=(a<<10)-((a<<4)+(a<<3));//умножить на 1000
int d=(a<<3)+(a<<1);//умножить на 10


Подскажете как поделить на 10,100,1000 любого числа 'a' со смещением(сдвигом)? Целочисленный
int (остаток от деления не важен).
    


Ответы

Ответ 1



Запросто :) 0.110 = 0.00011001100110012. То есть деление на 10 — это 1 / 16 + 1 / 32 + 1 / 256 + 1 / 512 + ... Дальше пояснять? :) А если серьезно - возьмите книгу Уоррена «Алгоритмические трюки для программистов», там есть глава 10, «Целое деление на константы». Там много стоящего. То же деление на 10: unsigned divu10(unsigned n) { unsigned q, r; q = (n >> 1) + (n >> 2); q = q + (q >> 4); q = q + (q >> 8); q = q + (q >> 16); q = q >> 3; r = n - q * 10; return q + ((r + 6) >> 4); // return q + (r > 9); }

среда, 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)); }

четверг, 19 декабря 2019 г.

Деление с округлением в большую сторону

#c_sharp #деление #math


Math.Round округляет по правилу, как заставить его округлять в большую сторону, или
какую другую функцию использовать?    


Ответы

Ответ 1



Math.Ceiling - к большему целому Math.Floor - к меньшему целому

Найти матрицу-множитель в произведении матриц при известном результате

#python #математика #numpy #матрицы #деление


Имеется произведение матриц a*b=c. Причем произведение матриц - это результат numpy.dot,
а не поэлементное произведение. Известны матрицы a и c. Требуется найти матрицу b.
Каким образом это можно сделать в python, не прибегая к решению системы уравнений с
множеством неизвестных? Если просто делить numpy.matrix, то получается совсем не тот
результат.

Вот пример:

import numpy as np
a = np.matrix([[ 1.,  2.],[ 3.,  4.]])
c = np.matrix([[ 2.],[ 1.]])
c/a
Out[201]: 
matrix([[ 2.        ,  1.        ],
        [ 0.33333333,  0.25      ]])


Решил письменно обратную задачу, получил ответ:

([[-3. ],
  [ 2.5]])


Проверяем:

b= np.matrix([[-3. ],[ 2.5]])
a*b
Out[207]: 
matrix([[ 2.],
        [ 1.]])


Если переводить в ndarray, то то же самое получается:

c.getA()/a.getA()
Out[213]: 
array([[ 2.        ,  1.        ],
       [ 0.33333333,  0.25      ]])

    


Ответы

Ответ 1



Воспользуйтесь обратной (inverse) матрицей: In [224]: b = np.linalg.inv(a) * c In [225]: b Out[225]: matrix([[-3. ], [ 2.5]]) Это будет работать для объектов типа numpy.matrix. Если a и c - объекты типа numpy.ndarray, то нужно использовать dot product (как в ответе @MarianD): In [8]: np.linalg.inv(a).dot(c) Out[8]: matrix([[-3. ], [ 2.5]]) PS использование dot product (операции умножения матриц как это понимается в линейной алгебре) - является более универсальным решением, т.к. оно правильно работает как для объектов типа numpy.matrix так и для numpy.ndarray: In [10]: np.linalg.inv(a.getA()).dot(c.getA()) Out[10]: array([[-3. ], [ 2.5]]) Пояснение: A * B = C | умножим обе части на A-1 умножение матриц операция некомутативная, т.е. A * B != B * A, поэтому чтобы получилась единичная матрица будем делать так: A-1 * A * B = A-1 * C => B = A-1 * C UPDATE: во многих случаях гораздо выгоднее решить систему уравнений, по сравнению с нахождением обратной матрицы (спасибо @jfs за подсказку): In [328]: b = np.linalg.solve(a, c) In [329]: b Out[329]: matrix([[-3. ], [ 2.5]]) Вот некоторые из преимуществ подхода решения системы линейных уравнений по сравнению с нахождением обратной матрицы: решение СЛУ (системы линейных уравнений) дает более точные численные результаты по сравнению с методами, использующими перемножение матриц. Пример скалярного произведения возвращающего неточный результат при использовании разреженных матриц (sparse matrices) есть методы, позволяющие найти решение и возвращающие также разреженные матрицы (если это возможно), что существенно экономит использование памяти. Обратная же матрица в общем случае не будет разреженной и может занимать на несколько порядков больше памяти. Например разреженная матрица размерности 1.000.000 x 1.000.000 у которой всего 1.000.000 ненулевых элементов (например единичная матрица или такая, у которой в каждой строке/столбце по одному ненулевому элементу) легко поместится в памяти и займет приблизительно: объем памяти необходимый для данного типа (np.int8, np.int16, np.int32, np.int64, np.float64, etc.) плюс небольшие накладные расходы (информация о позиции ненулевых элементов в разреженной матрице). Если преобразовать такую матрицу в обычную или найти обратную ей то в результате надо будет хранить в памяти уже 1.000.000 x 1.000.000 = 1.000.000.000.000 (один триллион элементов, или около 3.6 TiB для 32-битных элементов)

Ответ 2



Произведением матриц очевидно во вашем случае не разумеется код a * b что в numpy значит просто произведение элементов на согласных позициях, но математическое произведение (скалярное произведение строк матрицы a со столбцами матрицы b, что в numpy записывают как np.dot(a, b) или - более просто - a.dot(b) (что нужно использовать для проверки результата). Подобно этому, простое деление c / a делением элемент по элементу (с автоматическим расширением матрицы c на 2 x 2) на согласных позициях - и это опять нет тем, что вам требуется). Из-за того решение вашего задания маленько сложнее: Tак как a * b = c влечет за собой (после произведения обух страниц уравнения слева на а-1) b = а-1 * c. Это в numpy записывают как np.dot(np.linalg.inv(a), c) или - более просто - np.linalg.inv(a).dot(c) что результат вашего задания.

четверг, 1 ноября 2018 г.

Деление с округлением в большую сторону

Math.Round округляет по правилу, как заставить его округлять в большую сторону, или какую другую функцию использовать?


Ответ

Math.Ceiling - к большему целому Math.Floor - к меньшему целому

среда, 31 октября 2018 г.

Найти матрицу-множитель в произведении матриц при известном результате

Имеется произведение матриц a*b=c. Причем произведение матриц - это результат numpy.dot, а не поэлементное произведение. Известны матрицы a и c. Требуется найти матрицу b. Каким образом это можно сделать в python, не прибегая к решению системы уравнений с множеством неизвестных? Если просто делить numpy.matrix, то получается совсем не тот результат.
Вот пример:
import numpy as np a = np.matrix([[ 1., 2.],[ 3., 4.]]) c = np.matrix([[ 2.],[ 1.]]) c/a Out[201]: matrix([[ 2. , 1. ], [ 0.33333333, 0.25 ]])
Решил письменно обратную задачу, получил ответ:
([[-3. ], [ 2.5]])
Проверяем:
b= np.matrix([[-3. ],[ 2.5]]) a*b Out[207]: matrix([[ 2.], [ 1.]])
Если переводить в ndarray, то то же самое получается:
c.getA()/a.getA() Out[213]: array([[ 2. , 1. ], [ 0.33333333, 0.25 ]])


Ответ

Воспользуйтесь обратной (inverse) матрицей
In [224]: b = np.linalg.inv(a) * c
In [225]: b Out[225]: matrix([[-3. ], [ 2.5]])
Это будет работать для объектов типа numpy.matrix. Если a и c - объекты типа numpy.ndarray, то нужно использовать dot product (как в ответе @MarianD):
In [8]: np.linalg.inv(a).dot(c) Out[8]: matrix([[-3. ], [ 2.5]])
PS использование dot product (операции умножения матриц как это понимается в линейной алгебре) - является более универсальным решением, т.к. оно правильно работает как для объектов типа numpy.matrix так и для numpy.ndarray
In [10]: np.linalg.inv(a.getA()).dot(c.getA()) Out[10]: array([[-3. ], [ 2.5]])

Пояснение:
A * B = C | умножим обе части на A-1
умножение матриц операция некомутативная, т.е. A * B != B * A, поэтому чтобы получилась единичная матрица будем делать так:
A-1 * A * B = A-1 * C
=>
B = A-1 * C
UPDATE: во многих случаях гораздо выгоднее решить систему уравнений, по сравнению с нахождением обратной матрицы (спасибо @jfs за подсказку):
In [328]: b = np.linalg.solve(a, c)
In [329]: b Out[329]: matrix([[-3. ], [ 2.5]])
Вот некоторые из преимуществ подхода решения системы линейных уравнений по сравнению с нахождением обратной матрицы:
решение СЛУ (системы линейных уравнений) дает более точные численные результаты по сравнению с методами, использующими перемножение матриц. Пример скалярного произведения возвращающего неточный результат при использовании разреженных матриц (sparse matrices) есть методы, позволяющие найти решение и возвращающие также разреженные матрицы (если это возможно), что существенно экономит использование памяти. Обратная же матрица в общем случае не будет разреженной и может занимать на несколько порядков больше памяти. Например разреженная матрица размерности 1.000.000 x 1.000.000 у которой всего 1.000.000 ненулевых элементов (например единичная матрица или такая, у которой в каждой строке/столбце по одному ненулевому элементу) легко поместится в памяти и займет приблизительно: объем памяти необходимый для данного типа (np.int8, np.int16, np.int32, np.int64, np.float64, etc.) плюс небольшие накладные расходы (информация о позиции ненулевых элементов в разреженной матрице). Если преобразовать такую матрицу в обычную или найти обратную ей то в результате надо будет хранить в памяти уже 1.000.000 x 1.000.000 = 1.000.000.000.000 (один триллион элементов, или около 3.6 TiB для 32-битных элементов)