Как да получите усилващи части с много точност?

Да кажем, че имам този номер:

// 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`.

Както и да е, знае ли някой как да направя това, което се опитвам да постигна?

За протокола, имам нужда от това, за да изразя голямо десетично число като десетичен знак на C# в името на оперативната съвместимост.


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


Отговори (3)


От документацията за усилване задната част е умишлено непрозрачна, тъй като може да се промени по всяко време без предупреждение. (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# Decimal. Вижте ръководството относно изискванията за бекенда на 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 позволява това. Просто се опитвах да предложа решение, че е 23:00 и имате нужда от него утре. Може би си струва да гласувате против, не знам. - person AnthonyFoiani; 25.06.2014
comment
Забавен анекдот: Опитах се да създам #define private public; мем NO REGRETS във вътрешния генератор на мемове в настоящата ми компания... само за да бъде пренасочен към съществуващ пример. Така че предполагам, че не съм единствената луда душа с тази идея. :) - person AnthonyFoiani; 25.06.2014