LINUX.ORG.RU

Перевод из n-ной системы счисления в 10-ную

 ,


0

2

Луа позволяет преобразовать до 36ной системы счисления в 10ю включительно, а понимает кто нибудь как сделать больше? Алгоритм, суть преобразования.

Вот есть у меня функция:

function numCod(num)
    if num == 0 then
        return '0'
    end
    local neg = false
    if num < 0 then
        neg = true
        num = num * -1
    end
    local hexstr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWZYZabcdefghijklmnopqrstuvwxyzАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЭЮЯабвгдеёж"
    local result = ""
    while num > 0 do
        local n = math.fmod(num, 100)
        result = string.utf8sub(hexstr, n + 1, n + 1) .. result
        num = math.floor(num / 100)
    end
    if neg then
        result = '-' .. result
    end
    return result
end

А как теперь расшифровать? Сделать обратное преобразование.

★★★★★

если мне память не изменяет - то формула была такая Сумма элементов (от i=0 до n-1) X[x_i]*10^i, где X - это ассоциативный массив (ключем выступает название цифры в исходной системе, а значением его значение в 10 (например в 16 - это будет 0-0 1-1 2-2 .. A-10,B-11,F-15)), а x_i - это цифра числа (отсчет начинается справа)

Silerus ★★★★
()
Ответ на: комментарий от nionio35

Стоп.. Я знаю с какой буквой ассоциируются у меня десятичные. Допустим если производить действия с десятичными и переношу на свою. Есть у нас число «жжж». Реверсируем его и начинаем с начала: «ж = 99». Остается «жж». Берем еще «ж = 99» и остается последня "ж = 99. Но что мне это дается не могу понять.

Стоп. Я могу просто взять последний символ, перевести его в десятичную и просто стрингом приравнять к следущем? Приставить как римское? Я ничего не упустил? Допустим, берем число 819. В переводе это 8J. J = 19/ Остается 8. 8 .. J(19) = 819. Хм.. Не может быть так все просто.

Ох, я кажется дзен сейчас поймал. Я просто беру по одному символу, напрямую перевожу его через таблицу и состыковываю вместе. Я ведь прав? Вроде прав. Всем спасибо.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

ж = 99. Последний символ в ряду «0123456789ABCDEFGHIJKLMNOPQRSTUVWZYZabcdefghijklmnopqrstuvwxyzАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЭЮЯабвгдеёж»

Но вычислять ведь ничего не надо, разве я не прав? У нас уже все есть в строке. Каждая ж = 99. Значит мы просто делаем 99 .. 99 .. 99 и получает 999999. Все. Никаких вычислений.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LightDiver

А основание системы у тебя какое? Я не хочу твои символы пересчитыавать.

Значит мы просто делаем 99 .. 99 .. 99 и получает 999999

Мне кажется ты упускаешь из виду основание системы.

ЗЫ, у тебя кажется основание 102, а ж=101=10+25+25+33+8. Откуда взял 99?

ya-betmen ★★★★★
()
Последнее исправление: ya-betmen (всего исправлений: 1)
Ответ на: комментарий от LightDiver

нужен набор символов(0, 1, 2, …. ,ж), соотвествующее им значение и размер системы исчисления(основание). к примеру число жо1 в 64-тиричной системе будет равен(если ж=63, o=30, 1=1): ((63*64)+30)*64)+1. т.е. каждый символ подставляем значение, умножаем на размер, переходим к следующему. последний умножать ненадо. по идее так.

nionio35
()
Ответ на: комментарий от nionio35

Чот не совпадает..

function numeCod(str)
	local rez
	local r
	local hexstr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWZYZabcdefghijklmnopqrstuvwxyzАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя"
	local len = string.utf8len(str)
	local lenH = string.utf8len(hexstr)
	for j = 1, len do
		for i = 1, lenH do
			local r1 = string.utf8sub(hexstr,i,i)
			if r1 == string.utf8sub(str,j,j) then
				if j == 1 and j ~= len then
					r = i*128
				elseif j ~= 1 and j ~= len then
					r = (tonumber(r) + i) * 128
				elseif j == 1 and j == len then
					r = i
				elseif j ~= 1 and j == len then
					r = tonumber(r) + i
				end
				break
			end
		end
	end
	print(r)
end

Или я дурак. Шаг первый: умножаем номер первого символа на основание. У меня это 128. Шаг второй: прибавляем полученное к номеру второго символа и умножаем все на основание.. Шаг третий: Прибавляем номер последнего символа. И получаем.. Фигню получаем.

беру я numCod(15746), получаю «ы2». Беру numeCod(«ы2»), получаю 15875. Близко, но не то. Где я дурак?

Я где то на шаг ошибаюсь: FF у меня 2064, а 2064 получаются, как GG

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 4)
Ответ на: комментарий от nionio35

Спасибо огромное, кажется разобрался. Вот так вроде работает:

function numCod(num)
    if num == 0 then
        return '0'
    end
    local neg = false
    if num < 0 then
        neg = true
        num = num * -1
    end
    local hexstr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWZYZabcdefghijklmnopqrstuvwxyzАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя"
    local result = ""
    while num > 0 do
        local n = math.fmod(num, 128)
        result = string.utf8sub(hexstr, n, n) .. result
        num = math.floor(num / 128)
    end
    if neg then
        result = '-' .. result
    end
    return result
end
function numeCod(str)
	local rez
	local r
	local hexstr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWZYZabcdefghijklmnopqrstuvwxyzАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя"
	local len = string.utf8len(str)
	local lenH = string.utf8len(hexstr)
	for j = 1, len do
		for i = 1, lenH do
			local r1 = string.utf8sub(hexstr,i,i)
			if r1 == string.utf8sub(str,j,j) then
				if j == 1 and j ~= len then
					r = i*128
				elseif j ~= 1 and j ~= len then
					r = (tonumber(r) + i) * 128
				elseif j == 1 and j == len then
					r = i
				elseif j ~= 1 and j == len then
					r = tonumber(r) + i
				end
				break
			end
		end
	end
	return r
end
LightDiver ★★★★★
() автор топика
Ответ на: комментарий от nionio35

Да что ж это такое. Есть где то баг! Есть сбои в системе, но не могу понять где. Почти все работает, но встречаются числа, которые не совпадают. Например 962815. Что за ересь может быть то?

https://pastebin.com/URmYChWw

Вот такие функции использую. Скармливаю первой 962815.

Скармливаю результат второй и получаю: 962761. То есть на 54 меньше.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LightDiver

А кто его знает.
Исходник:

	if j == 1 and j ~= len then
	 r = i*128
	elseif j ~= 1 and j ~= len then
	 r = (tonumber(r) + i) * 128
	elseif j == 1 and j == len then
	 r = i
	elseif j ~= 1 and j == len then
	 r = tonumber(r) + i
	end

Then в первой строке моего кода нужно добавить.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)
Ответ на: комментарий от Forum0888

У меня почему то все работает….кроме отдельных редких чисел. Я хз как это чинить и вылавливать. Например не перегоняется 962815. А все остальное работает. Главное 962814 и 962816 работают как надо.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Сначала я перевожу из 10й в ХЗичную. Потом назад. В принципе все работает….кроме 1-2 результатов. Например при 128чной выдается хрень при цифре 2000000.. Но жить вроде можно.

У меня жесткие ограничения на передачу информации. Мне нужно передавать очень много информации при двух условиях: 1) Я могу передать не более 222 символов за раз. 2) Я не должен создавать спама запросами

Вот, приходится выкручиваться. При использовании 128ой системы, я могу сжать числа до 1999999 до 3 символов, например. Что уже юзабельно.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LightDiver

Вот смотрите.
Выполняете math.fmod(num, 128), получаете остаток 126, а затем выполняете string.utf8sub(hexstr, n + 1, n + 1).
Как бы 126 больше длины utf8 строки ...

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 1)
Ответ на: комментарий от Forum0888

Я уже исправил на:

function numCod(num)
    if num == 0 then
        return '0'
    end
    local neg = false
    if num < 0 then
        neg = true
        num = num * -1
    end
    local hexstr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWZYZabcdefghijklmnopqrstuvwxyzАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя"
    local result = ""
    while num > 0 do
        local n = math.fmod(num, 128)
        result = string.utf8sub(hexstr, n, n) .. result
        num = math.floor(num / 128)
    end
    if neg then
        result = '-' .. result
    end
    return result
end

То есть result = string.utf8sub(hexstr, n, n) .. result

С ним стало юзабельнее, но 1-2 числа выдают изредка сбои. Как с 2000000

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LightDiver

А результат?

Фирма 1С в 1С 7.7 для ID объектов использовала 36-ричную кодовую систему.
При этом для числовых полей в DBF выделялось меньше места.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)
Ответ на: комментарий от LightDiver

У меня жесткие ограничения на передачу информации. Мне нужно передавать очень много информации при двух условиях: 1) Я могу передать не более 222 символов за раз. 2) Я не должен создавать спама запросами

А кто мешает просто передавать числа в бинарном виде? Вы получите предельно компактный вывод (по основанию 256).

А ваш бред с алфавитом с использованием русских букв разбивается о то, что русские буквы кодируются больше чем одним байтом. Или вы должны будете использовать однобайтовые кодировки

PPP328 ★★★★★
()
Ответ на: комментарий от LightDiver

для «простоты» можно считать основанием например 256 если у тя не вся байты могут быть цифрами тогда у тя не все числа будут представимы

если же ты будешь например использовать что каждый байт в 10 раз больше меньшего то тогда даже при не всех символах разрешимых для представления чисел все числа будут представимы в такой смешанной системе это во первых и во вторых у многих чисел будет множество различных представлений

собственно ёто база - wats up doc?

qulinxao3
()
Ответ на: комментарий от LightDiver

Короче я хз что там с кодом, ибо с телефона читать неудобно, а луу без словарая нигугу. Вот набросок на жс


var digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzАБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзиклмнопрстуфхцчшщъыьэюя#@₽'

function toDec(number, radix) {
    var result = 0;
    if (radix>= digits.length) {
        throw 'Invalid radix ' +radix; 
    }
    for (var i=number.length-1, pos=0; i>=0; i--,pos++){
        var digit = number[i];
        var value = digits.indexOf(digit);
        if (value >= radix || value < 0){
            throw 'Invalid digit ' + digit;
        }
        result+=value*Math.pow(radix, pos);
    }
    return result;
}

function fromDec(number, radix) {
    if (radix>= digits.length){
        throw 'Invalid radix ' + radix;
    }
    var result = '';
    while (number >= radix) {
        var rem = number % radix;
        var digit = digits[rem];
        result = digit + result;
        number = Math.floor(number/radix);
    }
    if (number > 0){
        result = digits[number] + result;
    } 
    return result;
}

var res = fromDec(2000000, 128);
console.log(res);
var back = toDec(res, 128);
console.log(back);

//ь90
//2000000
ya-betmen ★★★★★
()
Ответ на: комментарий от Forum0888

Ну, результат странный. В основном работает. Но на двух миллионах просто выдает всю таблицу символов, например. Может еще где сбои есть. Увижу на практике. При 128чной системе числа до 2 миллионов передаются не более чем 3 символами, а это уже очень хорошо. При подходе к основанию в 1000 начинаются проблемы с быстродействием при вычислении..

Там же у меня два цикла, один вложенный в другой. Сначала мы перебираем все числа заготовки, потом сравниваем вообще со словарем в * чисел. Вот я и думаю, а нельзя ли как то избавиться от такого подхода и сделать менее затратным проход ресурсно? После основания в 1000 возникает весьма заметный микролаг при каждом вычислении, а это очень плохо. Вот представь, что пара сотен клиентов начнут регулярно отправлять запросы на шифровку-расшифровку.

А 36-ричную систему и дурак может.. Это же без вычислений встроено даже в луа сразу. Как я понял вчера, потому что это вот эти символы: «0123456789ABCDEFGHIJKLMNOPQRSTUVWZYZ».

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от PPP328

Это древнючий игровой сервер вовки. Он не делает различий в ограничениях между кириллицей и латиницей. Там жесткое ограничение просто на общее количество символов любых. Там даже для работы с utf8 приходится вон использовать свои реализации string’a, потому что луа не умеет кириллицу.

Как он позволяет передать инфу, так и передаю.

А можно немножко подробнее про компактный вывод бинарного вида по основанию 256? Я не программист, я использую то, что придумал сам пока или что нагуглил.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LightDiver

А можно немножко подробнее про компактный вывод бинарного вида по основанию 256?

Посмотрите, что такое тип uint8_t. Иначе мне придется тут лекцию читать

PPP328 ★★★★★
()

Луа позволяет преобразовать до 36ной системы счисления в 10ю включительно, а понимает кто нибудь как сделать больше?

Я так понимаю, 36 же появилось не просто так, 36=10+26, на основании 36 у тебя кончился латинский алфавит, откуда дальше будешь «цифры» брать? Да, можно подогнать ещё греческий алфавит и кириллицу, но там уже преобразование будет сильно сложнее, надо определять, в какой диапазон кодов символ попадает.

hobbit ★★★★★
()
Ответ на: комментарий от LightDiver

Я могу передать не более 222 символов за раз.

Как уже написали, русские буквы кодируются 2 байтами. 222 — это точно ограничение на символы, а не на байты? Если второе, то вся «экономия» идёт лесом.

Это древнючий игровой сервер вовки.

Если это тот, про который я подумал, он же вроде опенсорсный. Проще, возможно, патчингом самого сервера заняться (потом, правда, придётся убедить хозяев инстанса обновиться).

hobbit ★★★★★
()
Ответ на: комментарий от PPP328

https://wowwiki-archive.fandom.com/wiki/API_SendAddonMessage

Вот единственный вариант, что я знаю.

" The combined length of message and prefix can be at most 254 characters (255th is the tab character used to delimit the two) length above 254 will disconnect you.

except NULL (ASCII dec-ID 0) all characters (decimal ID 1-255) are allowed (in opposition to SendChatMessage where many characters are disallowed)"

Минус ключ.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от PPP328

А как я мог так жестоко ошибаться? И правда все символы, кроме «!»#$%&’()*+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}" - двубайтные. Итого, мой предел при всех ухищрениях - 92ая система счисления. И 8464 уникальных пары. Маловато, конечно…

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от Forum0888

У меня есть сервер (скрипты на луа) и n-клиентов (скрипты на луа). Основная логика и данные хранятся на сервере. Отрисовка всей этой логики у клиентов. Соответственно на каждое действие клиент должен отправить запрос серверу, сервер отправить ответный запрос клиенту. Слишком много запросов отправлять нельзя - забанят. Длина одного запроса может быть не более 254 байт.

Представь что одновременно 100 клиентов что то делают. Тут и наступает печаль.

https://youtu.be/1XEM8LBZvmY

Визуально это выглядит как то так плюс минус. И вот мне это все надо согласовать так, чтобы все работало и никто никого не забанил.

Итого, что я придумал: 1) Шифрую все данные в 92ой системе счисления 2) Добавляю очередь запросов: каждый запрос со стороны сервера отправляется не напрямую, а в очередь. Если очередь меньше 25 запросов - они выполняются мгновенно. От 25 отправляется на выполнение раз в секунду.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 3)
Ответ на: комментарий от LightDiver

Соответственно на каждое действие клиент должен отправить запрос серверу,

?

Почему сервер должен ограничивать количество действий игрока?

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 1)
Ответ на: комментарий от Forum0888

Открыть интерфейс. Интерфейс - это сто объектов, их параметры, кто их изменял. Доп объекты в них итд итп. Представь. Пользователь это открывает. Откуда он дожен получить информацию об объектах? Хранится она на сервере.

  1. Клик кнопки = запрос на сервер: покажи мне мои объекты

  2. Сервер видит этот запрос. Проверяет: есть ли у пользователя что то уже? Если нет - генерирует нулевой вариант и отправляет запрос с инфой клиенту. Если что то есть, формирует запрос с инфой и отправляет клиенту.

  3. Клиент видит ответный запрос с ифой, парсит его и отрисовывает.

Допустим у нас крестики-нолики 3х3 клетки. Игрок жмет кнопку и отправляет серверу: «Покажи мне поле», «имя_игрока».

Сервер видит запрос показать поле. Читает состояние поля: . И отправляет запрос: «Показываю», «хоххоххох», «имя_игрока».

Клиент игрока видит запрос: «Показываю» и начинает парсить: 1 клетка - х, вторая клетка - о, третья клетка х. Итд.

И так каждое действие. Все происходит на сервере и отправляется клиенту.

Если количество запросов от любой стороны превышает 25 в какой то малый промежуток времени, эта сторона отключается принудительно.

Теперь представь что одновременно пытаются открыть свои поля 100-200 игроков.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от LightDiver

наряду с кодированием в 92вариантов в байте длиной не более 254 байта

можно какой костыльный rle под сжатие запросов применить

али ваще арифметичное либо страшно сказать запросы с пользователей чисто ответы биты - весь поток генерит сервер - если есть задача минимизации потока от клиентов

так то (92 в степени 255) -1 достаточное пространство если словари на обоих сторонах достаточно проблемно ориентированны :)

qulinxao3
()
Последнее исправление: qulinxao3 (всего исправлений: 1)
Ответ на: комментарий от qulinxao3

Я наверное понял только междометия, если честно. Я начал программирование полгода назад. И с того, что мне тут скинули скрипт на луа. Мне бы пример и я б разобрался что тут написано.

LightDiver ★★★★★
() автор топика