Рекомендуемый способ приведения boost cpp_int к двойному?

У меня есть некоторый код, в котором я избегаю некоторых дорогостоящих делений, преобразовывая целое число повышения в двойное. Для реального кода я создам тип fp, достаточно большой, чтобы удерживать максимальное значение (экспонента). Для проверки я использую double. Итак, я делаю это:

#define NTYPE_BITS 512
typedef number<cpp_int_backend<NTYPE_BITS, NTYPE_BITS, unsigned_magnitude, unchecked, void> > NTYPE;
NTYPE a1 = BIG_VALUE;
double a1f = (double)a1;

Код, сгенерированный для этого приведения, довольно сложен. Я вижу, что он в основном перебирает все значения в a1 (сначала наименее значимые), масштабируя их по степени двойки. Теперь в этом случае я предполагаю, что максимальное количество элементов, которые могут повлиять на результат, - это последние два (64 бита для каждого элемента, а самый значимый элемент может иметь менее 64 бит). Есть лучший способ сделать это?


person Neill Clift    schedule 04.02.2021    source источник
comment
Я не думаю, что это поможет вам достичь вашей цели, но обычно вы должны использовать static_cast<double>(a1); вместо приведения типа c. stackoverflow.com/a/29983699/2601293   -  person J'e    schedule 04.02.2021


Ответы (1)


Во-первых, НИКОГДА не используйте гипс C-Style. (Зачем использовать static_cast‹int›(x) вместо (int )х?). Во-вторых, избегайте using namespace. (В-третьих, зарезервируйте для макросов имена с заглавными буквами).

Это сказало:

double a1f = a1.convert_to<double>();

Ваш билет.

Жить на Coliru

#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
namespace bmp = boost::multiprecision;

//0xDEADBEEFE1E104B1D00008BADF00D000ABADBABE000D15EA5E
#define BIG_VALUE "0xDEADBEEFE1E104B1D00008BADF00D000ABADBABE000D15EA5E"
#define NTYPE_BITS 512

int main() {
    using NTYPE = bmp::number<
        bmp::cpp_int_backend<
            NTYPE_BITS, NTYPE_BITS,
            bmp::unsigned_magnitude, bmp::unchecked, void>>;

    NTYPE a1(BIG_VALUE);

    std::cout << a1 << "\n";
    std::cout << std::hex << a1 << "\n";
    std::cout << a1.convert_to<double>() << "\n";
}

Отпечатки

1397776821048146366831161011449418369017198837637750820563550
deadbeefe1e104b1d00008badf00d000abadbabe000d15ea5e
1.39778e+60
person sehe    schedule 04.02.2021
comment
comment
Спасибо. a1.convert_to‹double›() делает практически то же самое, что и приведение. Теперь я решил, что в общем случае вам действительно нужно обработать все число. Например, если вы округляете операции с плавающей запятой, то число в форме 2^500+1 потребует сканирования всех библиотек, чтобы сгенерировать правильное значение. - person Neill Clift; 04.02.2021
comment
Я немного смущен, в чем проблема. Вы просили рекомендуемый/лучший способ. Это задокументированный путь. Если это делает то же самое, это нормально: это то, что рекомендуется. Я не совсем уверен, какое отношение операции округления с плавающей запятой имеют к cpp_int. - person sehe; 04.02.2021
comment
Я искал что-то, что работало лучше. Например, не прочитал весь номер, когда в этом не было необходимости. Я упоминаю об этом в вопросе. Как оказалось, я думаю, что это необходимо в случае округления, и я привожу пример выше. - person Neill Clift; 06.02.2021