Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 29, 2017 04:14:28

shiroi
Зарегистрирован: 2017-10-25
Сообщения: 23
Репутация: +  0  -
Профиль   Отправить e-mail  

система счисления с основанием n

py.user.next
out = re.sub(r'\(\d+\)', lambda mo: trans(mo.group()), number), re.sub это как я понимаю функция замены?а можно ее заменить например s.replace?

Офлайн

#2 Окт. 29, 2017 04:27:09

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

система счисления с основанием n

shiroi
а можно ее заменить например s.replace?
Нет. str.replace() ходит всегда по всей строке и для каждой цифры надо будет вызывать str.replace() снова. А re.sub() идёт один раз по строке и для каждой встреченной цифры делает сразу её замену. Замена у re.sub() умная (это распространённый шаблон для многих языков) и делает не просто замену строки на строку, а делает замену строки на результат функции, в которую передаётся найденная подстрока. Таким образом мы можем использовать отображение одних строк на другие (в виде словаря с парами), чтобы замена происходила по этому отображению. А в str.replace() можно только одну строку на одну строку заменять, поэтому она здесь не подходит. То есть re.sub() может искать, на что заменить совпавшую подстроку, а str.replace() может только тупо заменить определённую строку на определённую строку.

Вот пример гибкости re.sub()
  
>>> import re
>>> 
>>> re.sub(r'.', lambda mo: str(int(mo.group()) ** 2), '1234') # находим квадрат каждой цифры и пишем в результат
'14916'
>>>
>>> re.sub(r'.', lambda mo: mo.group() * 3, '1234') # утраиваем каждую цифру и пишем в результат
'111222333444'
>>>
>>> re.sub(r'(..)(..)', lambda mo: str(sum(map(int, mo.groups()))), '1234') # находим пары цифр, складываем двузначные числа и пишем в результат
'46'
>>>
>>> re.sub(r'.', lambda mo: print('see', mo.group()) or mo.group() * 2, '1234') # выводим найденные цифры, удваиваем их и пишем в результат
see 1
see 2
see 3
see 4
'11223344'
>>>



Отредактировано py.user.next (Окт. 29, 2017 04:44:04)

Офлайн

#3 Окт. 29, 2017 04:51:31

shiroi
Зарегистрирован: 2017-10-25
Сообщения: 23
Репутация: +  0  -
Профиль   Отправить e-mail  

система счисления с основанием n

py.user.next
эх, плюсов то много, правда у меня условие что не могу использовать сторонние библиотеки, поэтому re.sub не могу использовать

Офлайн

#4 Окт. 29, 2017 05:42:27

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

система счисления с основанием n

Вот ещё монолитный вариант.



Прикреплённый файлы:
attachment numbase_mono.tar.bz2 (948 байт)

Офлайн

#5 Окт. 29, 2017 12:06:00

shiroi
Зарегистрирован: 2017-10-25
Сообщения: 23
Репутация: +  0  -
Профиль   Отправить e-mail  

система счисления с основанием n

py.user.next
почти все правильно работает, кроме правой части, если после точки вводить что-нибудь, отличное от левой части, то он начинает неправильно считать, например: 12345.12345 в 36 он выводит правильно, 9ix.15wx, а вот если 12345.54321, то он выводит 9ix.15wx вместо 9ix.1920007162620232434

Офлайн

#6 Окт. 29, 2017 12:34:33

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

система счисления с основанием n

shiroi
почти все правильно работает, кроме правой части
Да я просто неправильно посчитал дробную часть, Забыл, как это делается (давно делали, где-то в 2002-м, если не в 2000-м ). Там другой алгоритм. Надо умножать дробь с нулевой целой частью на основание системы счисления и получающуюся целую часть брать в качестве очередной цифры. Надо всё переделать.

Add
Посмотрел тут, многие дроби получаются периодическими (бесконечными). Так что надо определиться с количеством знаков после запятой.

Пример перевода непериодической дроби из 10-чной в периодическую 2-ичную:
1.1d = 1.0(0011)b

Так что нужно брать сколько-то знаков после запятой.


shiroi
а вот если 12345.54321, то он выводит 9ix.15wx вместо 9ix.1920007162620232434
https://numsys.ru/
12345.54321 = 9IX.JK007GQL696Y2QPBJYPJUK92SRYXUG3S10HTZIKXYLEJSHLOX1

Фишка в том, что 19 и 20 надо тоже переводить в буквы. То есть там, в калькуляторе, где ты считал, это не учли.

А я вот считаю в Emacs'е
http://www.imageup.ru/img122/2900764/emacs-calc1.png.html
http://www.imageup.ru/img122/2900765/emacs-calc2.png.html
Это автоматический результат и вручную ещё посчитал обе цифры через умножение.

Повысил точность до 40 десятичных знаков
http://www.imageup.ru/img122/2900771/emacs-calc3.png.html



Отредактировано py.user.next (Окт. 29, 2017 13:35:17)

Офлайн

#7 Окт. 29, 2017 13:18:24

shiroi
Зарегистрирован: 2017-10-25
Сообщения: 23
Репутация: +  0  -
Профиль   Отправить e-mail  

система счисления с основанием n

py.user.next
ограничение 8 знаков после точки на выводе

Офлайн

#8 Окт. 29, 2017 13:36:52

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

система счисления с основанием n

shiroi
ограничение 8 знаков после точки на выводе
Видишь, надо точно знать, чтобы сначала юнит-тесты написать. Без юнит-тестов не будешь точно знать, работает ли функция без ошибок. Она же большая, всё в голове держать заманаешься, поэтому делаются юнит-тесты, которые её запускают и проверяют результат сразу. Если результаты всех тестов правильные, то он просто пишет точки. Если результат неправильный где-то, то он сразу пишет сообщение об ошибке (сбой теста).

Чтобы запускать юнит-тесты, у тебя должен быть установлен модуль pytest.
Потом просто в директории запускаешь
python3 -m pytest
и оно их находит и запускает все тесты.

Попозже посмотрю скрипт, сейчас надо проверить кое-что. Спешка в этих делах - дело неблагородное. При спешке часто потом приходится заново всё переписывать.



Отредактировано py.user.next (Окт. 29, 2017 13:45:33)

Офлайн

#9 Окт. 29, 2017 16:25:59

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

система счисления с основанием n

Да, видимо, в питоне такой алгоритм не прокатит из-за слишком малой точности у вещественных чисел

[guest@localhost numbase_mono]$ python3 -m pytest
================================== test session starts ===================================
platform linux -- Python 3.6.1, pytest-3.1.1, py-1.4.34, pluggy-0.4.0
rootdir: /home/guest/prog/tests/py/numbase_mono, inifile:
plugins: mock-1.6.2, cov-2.4.0
collected 14 items

test_numbase.py .F............

======================================== FAILURES ========================================
__________________________________ test_fraction_values __________________________________

def test_fraction_values():
lst = (
(1.1, 2, '1.000110011'),
(10.5, 2, '1010.1'),
(255.255, 16, 'ff.4147ae147a'),
(12345.12345, 36, '9ix.4fzolfdnfyd'),
(12345.54321, 36, '9ix.jk007gql696'),
)
for i1, i2, o in lst:
> assert f(i1, i2) == o
E AssertionError: assert '9ix.4fzolfdl0g' == '9ix.4fzolfdnfyd'
E - 9ix.4fzolfdl0g
E ? ^^^
E + 9ix.4fzolfdnfyd
E ? ^^^^

test_numbase.py:26: AssertionError
========================== 1 failed, 13 passed in 0.05 seconds ===========================
[guest@localhost numbase_mono]$
Как только начинаешь выходить за пределы точности при умножении дробной части, она начинает давать неправильный результат.

Так что тут, походу, другой алгоритм надо применять: сначала убрать плавающую точку из числа, потом проводить вычисления, а потом возвращать её обратно с учётом новой системы счисления.



Отредактировано py.user.next (Окт. 29, 2017 16:30:15)

Офлайн

#10 Окт. 30, 2017 01:41:13

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

система счисления с основанием n

В общем, небольшие вещественные числа она правильно вычисляет, но когда число становится больше по точности (когда исходная дробь растёт), начинаются глюки.

Поковырял это математически, можно там замутить рекурсивную функцию, если в питоне точности не хватает.

Например:
0.12d == 0.(1EB85)h

Приводим к дробному виду
12 / 100 = x / 256

Находим x
x = (12 * 256) / 100 = 30.72

Получаем равное соотношение (слева в десятичной системе, справа - в 16-ричной)
12 / 100 = 30.72 / 256

Дальше 30.72 переводим по частям в 16-ричную систему
30 = 1E
0.72 = 0.(B851E) (это так же переводится - приводится к дроби и так далее 72 / 100 = x / 256 … )

Потом склеиваем 1E и 0.(B851E) и получаем x в 16-ричной системе
0.1EB851E



Отредактировано py.user.next (Окт. 30, 2017 01:56:59)

Прикреплённый файлы:
attachment numbase_mono.tar.bz2 (1,1 KБ)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version