<bgdev />free

Вход Регистрация

[РЕШЕНО (дано този път наистина)] Малко математика като за полу-, цели и още по-цели идиоти
1

0 1 2
#20425 (ツ) гофи2
Последно редактирано на 04.12.2020 от гофи2, видяно: 2123 пъти.

Дойде ми време да се възползвам, че попаднах във форум дето има математици.

Проблема ми е следния. Дадена ми е една ел. таблица и трябва да въвеждам IBAN в нея. Е да де, ама аз не съм сигурен в себе си и искам да съм сигурен, че съм ги въвел правилно. Това да проверя, че е 22 знака и има верен БАЕ не ме успокоява. Искам да съм сигурен.

Според Наредба 13 на БНБ (писана по европейски стандарт) IBAN се преобразува в число, след което се взима неговия модул 97. Всичко това е прекрасно, докато се оказа, че електронната таблица (АОО в моя случай) не умее да борави (смята) с големи числа.

Преди седем години, когато правих подобно нещо на Perl, просто заредих приставка за BigInt и заспа. Но тук нямам такава екстра.

Та въпроса е, има ли начин тази сметка някак си да се разбие на повече стъпки с по-малки числа, така, че в крайна сметка да се получи точна сметка?

Би трябвало да може да се направи. Преди да има компютри, хората са ги смятали тия неща на ръка. Значи не може да не са измислили някакъв алгоритъм за по-лесни сметки.

Добронамерени да светнат един ламер, има ли?

#20426 (ツ) ФейкПрофил
Създадено на 04.12.2020, видяно: 2109 пъти.

Има начин:)

#20427 (ツ) ФейкПрофил
Създадено на 04.12.2020, видяно: 2108 пъти.

Провери ли в уикито ?


Modulo operation on IBAN

Any computer programming language or software package that is used to compute D mod 97 directly must have the ability to handle integers of more than 30 digits. In practice, this can only be done by software that either supports arbitrary-precision arithmetic or that can handle 220 bit (unsigned) integers,[Note 2] features that are often not standard. If the application software in use does not provide the ability to handle integers of this size, the modulo operation can be performed in a piece-wise manner (as is the case with the UN CEFACT TBG5 Javascript program).

Piece-wise calculation D mod 97 can be done in many ways. One such way is as follows:[14]

    Starting from the leftmost digit of D, construct a number using the first 9 digits and call it N.[Note 3]
    Calculate N mod 97.
    Construct a new 9-digit N by concatenating above result (step 2) with the next 7 digits of D. If there are fewer than 7 digits remaining in D but at least one, then construct a new N, which will have less than 9 digits, from the above result (step 2) followed by the remaining digits of D
    Repeat steps 2–3 until all the digits of D have been processed

The result of the final calculation in step 2 will be D mod 97 = N mod 97.
Example

In this example, the above algorithm for D mod 97 will be applied to D = 3214282912345698765432161182. (The digits are colour-coded to aid the description below.) If the result is one, the IBAN corresponding to D passes the check digit test.

    Construct N from the first 9 digits of D

        N = 321428291

    Calculate N mod 97 = 70
    Construct a new 9-digit N from the above result (step 2) followed by the next 7 digits of D.

        N = 702345698

    Calculate N mod 97 = 29
    Construct a new 9-digit N from the above result (step 4) followed by the next 7 digits of D.

        N = 297654321

    Calculate N mod 97 = 24
    Construct a new N from the above result (step 6) followed by the remaining 5 digits of D.

        N = 2461182

    Calculate N mod 97 = 1

From step 8, the final result is D mod 97 = 1 and the IBAN has passed this check digit test. 
#20428 (ツ) Courvoisier
Последно редактирано на 04.12.2020 от Courvoisier, видяно: 2105 пъти.

Нека вземем за пример IBAN BG80BNBG96611020345678;


Слагаш първите 4 отзад, за да стане BNBG96611020345678BG80

После минаваш през всеки ascii char и вземаш неговата стойност от ascii таблицата; 
	ако е letter (not a number), изваждаш 55
	
получаваш 1123111696611020345678111680

в един акумулатор, наречи го чексума, присвояваш първата стойност (на позиция 0), т.е., 1.

В цикъл въртиш от позиция 1 на 1123111696611020345678111680 до края на стойността
	чексума *= 10
	чексума + числото на текущата позиция
	чексума %= 97
	
накрая чексума трябва да ти е == 1

На netcore ще изглежда така:


class Program
    {
        static void Main(string[] args)
        {
            string input = "BG80BNBG96611020345678";

            string rearranged = input.Substring(4, input.Length - 4) + input.Substring(0, 4);

            StringBuilder sb = new StringBuilder();
            foreach (var @char in rearranged)
            {
                int temp;
                if (char.IsLetter(@char))
                    temp = @char - 55;
                else
                    temp = int.Parse(@char.ToString());
                sb.Append(temp);
            }

            string asciiCoded = sb.ToString();
            int checksum = int.Parse(asciiCoded.Substring(0, 1));
            for (var i = 1; i < asciiCoded.Length; i++)
            {
                checksum *= 10;
                checksum += int.Parse(asciiCoded.Substring(i, 1));
                checksum %= 97;
            }
            Console.WriteLine(checksum == 1);
        }
    }

Ако ти трябва за ексел, преведи си онлайн c#-а на vb и го сложи в macros в ексела.

#20430 (ツ) ФейкПрофил
Създадено на 04.12.2020, видяно: 2102 пъти.

Ето ти и друг вариант на ръст:


fn main() {
    let num = "3214282912345698765432161182";

    let mut result = 0u64;
    for &b in num.as_bytes() {
        let c = b as u64 - '0' as u64;

        result = (result * 10 + c as u64) % 97;
    }

    println!("Result: {}", result);
}
#20459 (ツ) гофи2
Създадено на 04.12.2020, видяно: 2085 пъти.

Благодаря Фейк! Ще се опитам да го разгадая.

Благодаря и на Courvoisier, но за съжаление директното ползване на mod(ulo) или каквито и да е действия върху големи числа не работят. Точно затова искам да разбия на по-малки.

#20460 (ツ) Courvoisier
Последно редактирано на 04.12.2020 от Courvoisier, видяно: 2082 пъти.

Няма да минеш 32767, макар понякога да минаваш 255. Мисля, че и Фейка на ръст ти ги смята в unsigned 64 bit, макар да се побира в по- малко. Мисля, че в най- лошия случаи ще ти остане 96, което ще умношиж по 10 и после да добавиш 9, което ще е 969. Трябва ти арей от char-ове и 16-bit numeric.

Какво е AOO?

#20461 (ツ) Дон Реба
Създадено на 04.12.2020, видяно: 2081 пъти.
гофи2

Благодаря и на Courvoisier, но за съжаление директното ползване на mod(ulo) или каквито и да е действия върху големи числа не работят. Точно затова искам да разбия на по-малки.

в неговия метод чексумата е малко число. не мога с един поглед да кажа дали бачка, по математика бях на четворки, но може и да бачка

#20462 (ツ) гофи2
Създадено на 04.12.2020, видяно: 2077 пъти.
Courvoisier

Няма да минеш 32767, макар понякога да минаваш 255.

Ами в ел. таблици няма конкретно int (прави вътрешни преобразувания за оптимизация), както би било в Ц. И явно сваля все пак осем байта, щом прави проблем. Проверих в Интернет и буквално закръгля до най-близкото цяло число. А на мен ми трябва остатъка. Кофти тръпка.

#20463 (ツ) гофи2
Създадено на 04.12.2020, видяно: 2075 пъти.
Courvoisier

Какво е AOO?

Извинявам се! Понякога не се усещам, че не говоря със себеподобни.

Apache OpenOffice

#20465 (ツ) гофи2
Последно редактирано на 04.12.2020 от гофи2, видяно: 2069 пъти.
Дон Реба

в неговия метод чексумата е малко число. не мога с един поглед да кажа дали бачка, по математика бях на четворки, но може и да бачка

Сега го забелязах, но, колкото и да препрочитам, не успявам да разбера, на какво казва контролен сбор. Ц Диез не е точно моето, ъ-ъ-ъ. Казах ли, че съм ламер?

Това за ascii е гениано и ми спестява много. В наредбата е дадено като таблица, без да се казва, как е определена.

доп.

===

Даже не стигам до числото му. Според мен трябва да е 9661102034567811168011231116, а не 1123111696611020345678111680.

#20467 (ツ) ФейкПрофил
Създадено на 04.12.2020, видяно: 2068 пъти.

 на ръст ти ги смята в unsigned 64 bit

по навик :), но числото едва ли ще мине 1000, така че стига ексела ти да може да работи с числа до 1000 всичко ще е точно

#20468 (ツ) Courvoisier
Последно редактирано на 04.12.2020 от Courvoisier, видяно: 2067 пъти.

Хммм... като правиш integer % 97 ти прави грешка? Я дай скрипта, пише, че е доста подобен на VB.

От друга страна, в гугъл шийт макросите се пишат с javascript и си имаш API. Може би най- интелигентното решение, ако не ти пука, че гугъл ти виждат данните.

#20471 (ツ) Courvoisier
Последно редактирано на 04.12.2020 от Courvoisier, видяно: 2058 пъти.
гофи2
Дон Реба

в неговия метод чексумата е малко число. не мога с един поглед да кажа дали бачка, по математика бях на четворки, но може и да бачка

Сега го забелязах, но, колкото и да препрочитам, не успявам да разбера, на какво казва контролен сбор. Ц Диез не е точно моето, ъ-ъ-ъ. Казах ли, че съм ламер?

Това за ascii е гениано и ми спестява много. В наредбата е дадено като таблица, без да се казва, как е определена.

доп.

===

Даже не стигам до числото му. Според мен трябва да е 9661102034567811168011231116, а не 1123111696611020345678111680.

Като сложиш първите 4 отзад, става BNBG96611020345678BG80. Обърни внимание, че IBAN е с ГЛАВНИ БУКВИ. Главните букви са ASCII - 55. Числата си остават числа. Трябва да получиш голямо число, което може да е стринг (или арей от char), като всяка буква е нейния ASCII Код - 55, а числото се запазва. Ако погледнеш кой символ какво е в ASCII (http://www.asciitable.com/) ще получиш:

B = 66 - 55; защо изваждаш 55 не мога да ти кажа, но алгоритъмът е такъв = 11
G = 78 - 55 = 23
B = 66 - 55 = 11
G = 71 - 55 = 16
9 = 9
6 = 7
6 = 6
1 = 1
1 = 1
0 = 0
2 = 2
0 = 0
3 = 3
4 = 4
5 = 5
6 = 6
7 = 7
8 = 8
B = 66 - 55 = 11
G = 71 - 55 = 16
8 = 8
0 = 0

Така получаваш 11 23 11 16 9 7 6 1 1 0 2 0 3 4 5 6 7 8 11 16 8 0. Но ще го обработваш цифра по цифра, а не число по число.

После, акумулаторът ти си присвоява цифрата на позиция 0 = 1

после в цикъл въртиш останалите от позиция 1 до позиция броя на цифри. Т.е., започваш от Index=1
1[1]23111697611020345678111680
1 * 10 = 10
10 + 1 = 11
11 % 97 = 11

11[2]3111697611020345678111680
11 * 10 = 110
110 + 2 = 112
112 % 97 = 15

112[3]111697611020345678111680
15 * 10 = 150
150 + 3 = 153
153 % 97 = 56

1123[1]11697611020345678111680
56 * 10 = 560
560 + 1 = 561
561 % 97 = 76

.... (прескачаме малко итерации) ...

112311169761102034567811168[0]
68 * 10 = 680
680 + 0 = 680
680 % 97 = 1

Крайният резултат е 1. За да е валиден IBAN трябва да е 1.

Worst case, ще имаш 96 (96 % 97 = 96) от предната итерация, която ще се умножи по 10 и ще се прибави 9, но после ще го намалиш, защото ще направил модуло 97.

#20472 (ツ) code2
Създадено на 04.12.2020, видяно: 2055 пъти.

Не съм гледал какви кодове са ти дали, но си спомням още от училище, че се учеха така наречените признаци за делимост на 3 и на 11. Всъщност точно такъв механизъм се ползва за да се вземе нужния остатък. Помня също, че имаше някакъв признак за делимост на 19, но той беше съвсем друга бира (че да не беше и твърд алкохол...).

#20474 (ツ) Courvoisier
Последно редактирано на 04.12.2020 от Courvoisier, видяно: 2054 пъти.

За 3, сбора на цифрите също се дели на 3. Например 15 => 1 + 5 = 6 % 3 = 0. Но това как ти помага за модулo 97?

#20475 (ツ) code2
Създадено на 04.12.2020, видяно: 2051 пъти.
Courvoisier

За 3, сбора на цифрите също се дели на 3. Например 15 => 1 + 5 = 6 % 3 = 0. Но това как ти помага за модулус 97?

В доказателството на споменатото "За 3, сбора на цифрите също се дели на 3." се използва взимане по модул 3 на числата 10^n, които точно в този случай са само единици. В този ред на мисли при 97 ще имаме число, което със сигурност е по-малко от 10*22*97=21340. А ако изчисляваш на всяка стъпка по модул няма да имаш числа по-големи от 11*97, независимост от дължината на числото.

Естествено горе споменатото не е толкова елегантно като очевидната техника за бързо умножение на полином, но пък е нещо сравнително познато.

#20499 (ツ) Дон Реба
Създадено на 05.12.2020, видяно: 2010 пъти.
гофи2
Дон Реба

в неговия метод чексумата е малко число. не мога с един поглед да кажа дали бачка, по математика бях на четворки, но може и да бачка

Сега го забелязах, но, колкото и да препрочитам, не успявам да разбера, на какво казва контролен сбор.

ами на това което в крайна сметка ще ти даде резултата от модул по 97 механизма на решението е "акумулатор с превъртане", нещо като циферблат на часовник. стрелката показва 5, добавяш и 3 "часа", показва 8. добавяш още 7 "часа" и вече показва 3 (15 мод 12). горното решение е същото, само че часовника ти има 97 "часа", а не 12. всяко поредно събираемо е малко, затова нямаш грижи. може би не е много нагледно за който не е виждал часовник със стрелки, ама по-нагледно не се сещам :)

#20501 (ツ) Delegate
Създадено на 05.12.2020, видяно: 2005 пъти.

Може и да не са виждали часовник с "ръце" , ама тука всички разбират от Diffie Hellman и съм сигурен, че са втрещявали момичетата в класа, като са познавали за секунди кой ден от седмицата е някаква случайна дата.

#20503 (ツ) гофи2
Създадено на 05.12.2020, видяно: 1996 пъти.

БЛАГОДАРЯ на всички, които се включиха в темата и дадоха от времето си. Най-много благодаря на Курвазие и Дон Реба, които обясниха алгоритъма точно като за полуидиот, какъвто за жалост или за радост съм.

Чудесни сте!

п.п. Разликата между голямото число на Курвазие и моето беше, понеже съм цял идиот и бях взел неговия IBAN, когато вече беше преместил последните четири знака отзад. Ама това го видях едва днес на сутрешното кафе. Снощи трябваше да готвя за домашните, след което слушах спортното шоу на „Дарик“, напих се лошо с ракия и дори не успях да гледам Сашо Диков.

0 1 2

[РЕШЕНО (дано този път наистина)] Малко математика като за полу-, цели и още по-цели идиоти
1

AsmBB v2.9 (check-in: 36c85c790bbb4625); SQLite v3.31.1 (check-in: 3bfa9cc97da10598);
©2016..2020 John Found; Licensed under EUPL. Powered by Assembly language Created with Fresh IDE