Как увеличить части числа с высокой точностью?

Скажем, у меня есть этот номер:

// bmp = boost::multiprecision
bmp::cpp_dec_float n("123456789.1234567891011121314");

его внутренние данные:

[0]  1         unsigned int
[1]  23456789  unsigned int
[2]  12345678  unsigned int
[3]  91011121  unsigned int
[4]  31400000  unsigned int
...  0
[15] 0         unsigned int

именно то, что я хочу получить; к сожалению, я не могу получить ни обе части моего номера как bmp::int128_t --например--, ни базовые данные моего номера.

То есть у меня вроде что-то вроде этого существует:

bmp::int128_t integerPart;
bmp::int128_t floatPart;
n.getParts(integerPart, floatPart);

or

auto&& data = n.data(); // which is actually private when using `cpp_dec_float`.

В любом случае, кто-нибудь знает, как сделать то, чего я пытаюсь достичь?

Для записи мне нужно это, чтобы выразить большое десятичное число как десятичное число С# для обеспечения совместимости.


person mister why    schedule 10.05.2013    source источник


Ответы (3)


Судя по документации boost, серверная часть намеренно непрозрачна, поскольку она может измениться в любое время без предупреждения. (Class template cpp_dec_float fulfils all of the requirements for a Backend type. Its members and non-member functions are deliberately not documented: these are considered implementation details that are subject to change.) с http://www.boost.org/doc/libs/1_55_0/libs/multiprecision/doc/html/boost_multiprecision/ref/cpp_dec_ref.html

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

В качестве альтернативы я бы порекомендовал вам взять строковое представление cpp_dec_float и самостоятельно разделить его на две части, используя конструкторы string или char* для базовых целочисленных типов, которые вас интересуют.

person Mark B    schedule 23.06.2014
comment
+1, с дополнительным примечанием, что общедоступная лицензия Boost позволяет копировать практически для любого использования, включая коммерческое. Если внутреннее представление, если какая-то версия - это именно то, что нужно/хочет OP, то, если владельцев Boost.MultiPrecision нельзя убедить заморозить одну реализацию, OP может заморозить ее самостоятельно. - person AnthonyFoiani; 25.06.2014

Я не знаю, если это вы ищете, попробуйте...

cpp_dec_float_100 myreal(100);
cpp_dec_float_100 int_part = myreal.backend().extract_integer_part();

Тип по-прежнему cpp_dec_float_100, но содержит только целую часть. Надеюсь, это поможет.

person Fernando Pelliccioni    schedule 23.01.2014

Я подозреваю, что вы, вероятно, можете использовать eval_frexp для получения значений, которые вы ищете, хотя вам все равно придется проверять, соответствуют ли они десятичному типу C#. См. руководство по требованиям к серверной части Boost.Multiprecision здесь: http://www.boost.org/doc/libs/1_53_0/libs/multiprecision/doc/html/boost_multiprecision/ref/backendconc.html

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

Сказав все это, вы можете быть непослушным и сделать что-то вроде:

#define private public
#define protected public
#include <boost/multiprecision/cpp_dec_float.hpp>
#undef private
#undef protected

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


Эй, спасибо за минус без комментариев. Это действительно полезно.

Чтобы уточнить мои комментарии выше:

Использование eval_frexp: после дальнейших исследований кажется, что eval_frexp(b, cb, pi) по-прежнему предлагает только степени 2, а не степени 10, как кажется, требуется для типа Decimal. Поэтому я подозреваю, что вам придется выполнять арифметические действия в длинной форме, если вы хотите использовать только общедоступный интерфейс.

Злоупотребление private членами: авторы и сопровождающие классов Boost.Multiprecision разработали их в соответствии с определенными рекомендациями; они, по-видимому, считали перспективу более важной, чем предоставление доступа к внутренней структуре:

Шаблон класса cpp_dec_float соответствует всем требованиям для типа Backend. Его члены и функции, не являющиеся членами, намеренно не документируются: они считаются деталями реализации, которые могут быть изменены. (http://www.boost.org/doc/libs/1_53_0/libs/multiprecision/doc/html/boost_multiprecision/ref/cpp_dec_ref.html)

Мое предложение, которое было четко помечено как «непослушное» и с предупреждением о том, что оно, вероятно, сломается в будущем выпуске, заключалось в том, чтобы навязать потребности дизайна OP выше потребностей автора B.MP.

Самый чистый метод может состоять в том, чтобы предложить изменение класса cpp_dec_float, где открыта внутренняя структура; учитывая убедительный вариант использования и анализ того, насколько код изменился или не изменился исторически, он может быть даже принят.

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

person AnthonyFoiani    schedule 12.05.2013
comment
Это был не я, но #defineing ключевые слова — это неопределенное поведение и (почти?) никогда не является надежным решением проблем. - person Mark B; 23.06.2014
comment
О, тут не поспоришь. Я попытался сформулировать исходный ответ (и мой язвительный комментарий о отрицательном голосовании), чтобы было ясно, что это не то, что является хорошей идеей для использования в производстве. Если OP действительно нуждается в этой возможности в долгосрочной перспективе, то, если они не могут убедить сопровождающих B.MP, они должны просто разветвить ее и включить в свою кодовую базу - BPL допускает это. Я просто пытался предложить решение, которое сейчас 11 вечера, и оно вам нужно завтра. Может быть, это стоит минуса, не знаю. - person AnthonyFoiani; 25.06.2014
comment
Забавный анекдот: я пытался создать приватный паблик #define; NO REGRETS мем во внутреннем генераторе мемов в моей текущей компании... только чтобы быть перенаправленным на существующий пример. Так что я думаю, что я не единственная сумасшедшая душа с этой идеей. :) - person AnthonyFoiani; 25.06.2014