Реализация типа Decimal для БД
Может быть у кого-то уже есть готовые решения? Или кто-нибудь знает, откуда надо начать копать?
Мне нужно разработать C++ класс, который из себя будет представлять десятичное число, в котором будет 20 знаков. Знаю, что это можно реализовать с помощью __int64, но для совместимости с другими платформами его не рекомендуется использовать. Слышал про воично-десятичное представление чисел (это когда две цифры хранятся в одном байте). Про способы хранения такого числа мне в принципе все понятно, но мне нужны работающие алгоритмы деления, умножения и прочие.
Может быть у кого-то уже есть готовые решения? Или кто-нибудь знает, откуда надо начать копать?
Это почему __int64 не будет работать на других платформах? Нужно всего лишь использовать компилятор, который это поддерживает. Занимать это будет 8 байт вместо 20 (или 10) на число, а работать будет гораздо быстрее и проще. Такой код будет быстрее выполнятся даже на 8-миразрядном компьютере.
Для того, чтобы составить алгоритм умножения чисел в двоично-десятичном формате достаточно всего лишь вспомнить операции сложения, умножения "в столбик" и деления "уголком".
Если вас интересует, зачем мне больше, то скажу: я работаю в фирме, которая делает проги для банков. У нас есть набор типов данных, среди которых тип Money - в нем 19 разрядов, среди которых 2 разряда после запятой. Я посмотрел его реализацию недавно - она страшная, ни одного комментария и все потенциально глючное, а мне надо сделать что-то устойчивое, понятное и удобное для доработок.
На самом деле проблема тут не только в совместимости, мне хочется создать класс, в конструктор которого я буду передавать количество разрядов или можно сделать шаблон. В __in64 только 20 разрядов вмещается. Что же мне делать, если захочется больше? Базы SQL же больше поддерживают.
Если вас интересует, зачем мне больше, то скажу: я работаю в фирме, которая делает проги для банков. У нас есть набор типов данных, среди которых тип Money - в нем 19 разрядов, среди которых 2 разряда после запятой. Я посмотрел его реализацию недавно - она страшная, ни одного комментария и все потенциально глючное, а мне надо сделать что-то устойчивое, понятное и удобное для доработок.
А не думал на счет быстрого? Можно оперируя 16/32-хбитными словами обрабатывать эффективно числа длиной больше 64 бит, последовательно.
А не думал на счет быстрого? Можно оперируя 16/32-хбитными словами обрабатывать эффективно числа длиной больше 64 бит, последовательно.
Благодарю за ответы, но они мне вряд ли помогут. Я ищу реальное описание работы с такими числами или сейчас начну сам ваять. С последовательной обработкой я знаком - сложение с запоминанием бита переноса и т. д., но мне нужна поддержка и деления, и умножения. Ну, может, sin() и cos() вычислять не придется - для этой цели можно и к double преобразовать, но вот умножение точно понадобится.
Ну, может, sin() и cos() вычислять не придется - для этой цели можно и к double преобразовать, но вот умножение точно понадобится.
Все до не могу просто. Если по твоим словам задача сводится просто к работе с целыми числами высокой разрядности, можешь поискать библиотеки, использующиеся в шифровании. Там ведь ключи до 4096 бит бывают.
Кстати, вопрос уже не раз поднимался на форуме, и даже ссылки давали. Ищи.
Все до не могу просто. Если по твоим словам задача сводится просто к работе с целыми числами высокой разрядности, можешь поискать библиотеки, использующиеся в шифровании. Там ведь ключи до 4096 бит бывают.
Кстати, вопрос уже не раз поднимался на форуме, и даже ссылки давали. Ищи.
Не хотел отвечать, потому что [COLOR=blue]полностью согласен с Freemanом[/COLOR], но всё-таки не удержался и добавил. Зря, наверно...
Если хочется попрограммировать, то знаю идею. Двоично-десятичная арифметика реализована в архитектуре IBM mainframe. Там это делается примерно так. (В деталях могу ошибаться, потому что уже давно не общался с такими машинами.)
Имеются упакованные числа. Они используются для хранения и обмена информацией.
Один десятичный знак занимает 4 бита. Для этого используются двоичные числа от 0000 до 1001.
Младшие десятичные знаки предшествуют старшим.
Знак числа находится в конце последовательности и представляется кодами 1010 для плюса и 1011 для минуса.
Для дробей используется десятичный разделитель с кодом 1100.
Коды 1101 и 1111 не используются.
Число занимает целое количество байт. При необходимости в старшем разряде добавляется 0.
Имеются распакованные числа. Они используются для вычислений.
Каждый значащий полубайт превращается в байт, десятичный разделитель выкидывается.
Сложение и вычитание делается над распакованными числами, выровненными так, чтобы позиции десятичного разделителя в операндах совпали. После выполнения операции число снова упаковывается.
Умножение и деление выполняется, как отметил уже Envel, над значащими цифрами "в столбик".
Синусы, косинусы и иже с ними в двоично-десятичном представлении не поддерживаются.
Максимальная точность представления — 255 десятичных знаков.
Работает крайне медленно.
Попробуйте реализовать такое же, если хотите, или найдите описание алгоримтов от IBM. Я думаю, они не секретны. Однако, портировать их не удастся, потому что они написаны на каком-то специальном ассемблере, предназначенном только для mainframe.
Удачи вам, г-н pushkin.
Если кто-нибудь хочет заиметь эти исходники, оставляйте свой e-mail - я вам их вышлю :)
Они написаны на C и реализуют операции с такими числами.
К слову сказать, в ассемблере x86 есть специальные команды для работы с BCD-числами. Только уже не помню, что конкретно они могут.