| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Алгоритмы > Как одном числе хранить сумму трех чисел |
| Автор: Delphist 17.3.2008, 20:14 |
| 1. Стала такая задача, есть три числа a, b, c в сумме они дают 100, a + b + c = 100; Нужно суммы этих чисел представить через какую-то функцию кодирования (или другим способом) в число, чтобы потом по этому числу применяя функции декодирования можно было получить эти три числа, т.е. SomeMathFuncCode(a, b, c) = d; SomeMathFuncDecode(d) = {a, b, c} 2. Как это же реализовать если, чисел > 3 т.е (a, b, c, d, ...) и сумма их равна не 100, а заданному числу X. Примечание: a, b, c - могут быть дробными |
| Автор: Sardar 17.3.2008, 20:43 |
| Пусть число ограничено 8 битами, тогда побитовым сдвигом влево все три числа и берём сумму (ну или OR побитовое если числа могут быть негативными). Обратно AND побитовое по маске, сдвиг обратно в право. В обычный uint(32) уложиться 4 таких числа, для других размерностей принцип тот же. Восстановить сумму из трёх произвольных по значению и размерам числа по моему не возможно. |
| Автор: 4d5a 17.3.2008, 21:03 | ||||
А почему бы не так
Тогда надо еще доказать что при выбранном методе 'уплотнения' они влезут в это число |
| Автор: Akina 17.3.2008, 21:12 |
| Исходная задача - это типичная задача хранения избыточных данных. Самое простое - это хранение минимально необходимых данных, которые позволяют восстановить недостающие. Например в исходном случае, если надо хранить ровно 3 числа (a,b,c), их сумма всегда равна 100 и они всегда неотрицательны, достаточно хранить одно число N = 100*a+b. Очевидно, что этого числа достаточно, чтобы восстановить всю тройку (a=N\100; b=N%100; c=100-a-b). Для любого другого варианта просто необходимо определить, какие данные являются избыточными, выбросить их, а из оставшихся составить выражение с однозначным соответствием. |
| Автор: VICTAR 17.3.2008, 21:17 | ||
Уже ответили... Ну не зря же я старался
|
| Автор: sergejzr 17.3.2008, 23:08 |
| Akina, как всегда - максимус элегантус! |
| Автор: Delphist 18.3.2008, 09:56 | ||
Твой метод не работает, если числа дробные. А мне нужен как раз для дробных чисел |
| Автор: Akina 18.3.2008, 10:02 | ||
А я не телепат. Хочешь получить решение для задачи, озвучив только треть условий? Впрочем, ПРИНЦИП от этого не меняется. |
| Автор: ama_kid 18.3.2008, 10:08 |
| Как вариант - можно рассмотреть случай с ограничением числа знаков после запятой: к примеру у тебя есть числа 21.29, 41.35 и 37.36. В сумме они дают требуемую сотню. Тогда переводим числа из дробного вида в целый путем умножения на 100: 2129+4135+3736 = 10000. Дальше все сводится к методу, описанному Akina... |
| Автор: Delphist 18.3.2008, 10:23 |
Неа не сводится, метод Akina работает с целыми числами (a, b, c) непревышающие 255 |
| Автор: ama_kid 18.3.2008, 11:01 | ||
N=10000*a+b = 10000*2129+4135=21294135 Восстанавливаем числа: a = N\10000 = 2129 (затем превращаем в дробное делением на 100) = 21.29 b = N%10000 = 4135 =>41.35 c = 100.00 - a - b => 37.36 P.S. Все это рассматриваю как пример, не больше. В конечном итоге надо исходить из конкретных данных, вполне возможно ограничение числа знаков после запятой некорректно... |
| Автор: Akina 18.3.2008, 13:41 | ||
Позволю себе процитировать себя же |
| Автор: Delphist 18.3.2008, 20:18 |
Не понял |
| Автор: sergejzr 18.3.2008, 21:29 | ||
Неверно, "размер" числа значения не имеет. От дробность - тоже можно избавиться (хотя информация о количестве знаков после запятой не сохраняетя) А вот методы со сдвигами как раз ограничивают "размер" сохраняемых чисел. |
| Автор: Akina 18.3.2008, 21:40 |
Да это тебя пока никто не понял. Ты до сих пор не сформулировал задачу ПОЛНОСТЬЮ. Со всеми условиями, в ти.ч. граничными. А мы, как дураки, гадаем на кофейной гуще, что же у тебя там собсно происходит и с чем именно. Я, например, до сих пор не знаю, какими могут быть эти а-бэ-цэ - только положительными или еще и нулевыми и даже отрицательными, простой они точности или двойной, или точность задана... Неужели трудно точно поставить задачу? |
| Автор: Delphist 19.3.2008, 15:19 |
числа a, b, c могут быть дробными, функции EnCode превращает их в одно число d (целое или дробное), а функция DeCode превращает из числа d их обратно в три числа a, b, c Вот собственно и все |
| Автор: mes 19.3.2008, 15:42 |
лучше тогда вопрос: а какими они не могут быть? так как вышеописанное условие не соответствует фразе |
| Автор: Akina 19.3.2008, 15:50 |
Извини за грубость, но термин "дробные" надо было забыть еще в детском саду. Real? Double? или какие там у вас в Дельфах есть типы... ограничения на значения есть? какие именно? |
| Автор: 4d5a 20.3.2008, 20:52 |
| Думаю из всего вышесказанного можно наконец то выпарить точную формулировку задачи: Даны три рациональных числа (a,b,c), представленных в виде десятичной дроби. Каждое число принадлежит промежутку [0;100]. Максимальное количество знаков(десятичных) после запятой равно X0. Для ввода и вывода чисел используется тип double: 8 byte. Найти функцию FY(Y1,Y2,Y3)->{Y0}, и обратную ей функцию FZ(Z0)->{Z1,Z2,Z3} которые удовлетворяют условию FY(FZ(V))=V (запись "->{Z1,Z2,Z3}" означает что функция возвращает три значения) Причем, ф-ия FY ставит в соответсвие одной тройке аргументов Y1,Y2,Y3 одно значение Y0, а ф-ия FZ сопоставляет одному значению Z0 одну уникальную комбинацию Z1,Z2,Z3. Т.е. имеет место однозначное соответствие. Реализовать FY,FZ двумя процедурами на унивесальном ЯП или в словестном виде. К примеру, X0=2 Замечание: изначально предпологается что в 8 байтах хватит места для a,b,c. За это предположение отвечает условие X0=2 Delphist, поправте если не так |
| Автор: 4d5a 20.3.2008, 21:27 | ||||
но если я правильно понял задачу, Вам уже дали общий метод ее решения (см. далее). В чем вопрос - то еще ????????
|
| Автор: Delphist 21.3.2008, 09:51 | ||
Все правильно, но X0 может меняться от 1 до 5 |
| Автор: Akina 21.3.2008, 10:19 |
Значит X0 = 5. Итого требуется хранение числа, состоящего из максимум 7 цифр. Следовательно: (long*64) Hash = 2**32 * (long*32) (a * 10**5) + (long*32) (b * 10**5) |