在编译时初始化double
Initializing double at compile-time
我正在通过模板元编程编写浮点运算的编译时实现。我的实现具有以下特点:
- 16位有符号整数指数。
- 32位无符号整数尾数,没有隐含的最高有效1(这样做是为了简化调试)。
类型如下:
template<bool S , std::int16_t E , std::uint32_t M>
struct number
{
static constexpr const bool sign = S;
static constexpr const std::int16_t exponent = E;
static constexpr const std::uint32_t mantissa = M;
};
操作工作得很好,但是现在我需要一个方法来在编译时提取这些值并获得相应的double
值。由于编译时算法的目标是加快计算速度,将解直接注入可执行程序,因此我需要一种方法来在编译时有效地初始化双常量。所以涉及std::pow( 2.0 , E )
的简单解是不允许的。
据我所知,双精度IEE754浮点数具有10位带符号指数和53位无符号整数尾号。我尝试的解决方案是通过联合使用类型双关语:
template<bool S , std::int16_t E , std::uint32_t M>
struct to_runtime<tml::floating::number<S,E,M>>
{
static constexpr const long unsigned int mantissa = M << (53 - 32);
static constexpr const int exponent = E + (53 - 32);
struct double_parts
{
unsigned int sign : 1;
int exponent : 10;
long unsigned int mantissa : 53;
};
union double_rep
{
double d;
double_parts parts;
};
static constexpr const double_parts parts = { .sign = ((bool)S) ? 0 : 1 , .exponent = exponent , .mantissa = mantissa };
static constexpr const double_rep rep = { .parts = parts };
static constexpr double execute()
{
return rep.d;
}
};
但是这个解决方案是不可移植的,调用未定义的行为(因为在做类型双关语时,我们读取尚未写入的联合成员),而且在实现转换时我也有一些问题(这个解决方案不返回正确的数字)。
是否有其他方法来初始化double
在编译时给定我的数据(符号,指数,尾数)?
您可以实现constexpr
pow2(std::int16_t)
,如:
constexpr double pow2(std::int16_t e)
{
return e == 0 ? 1. :
e > 0 ? 2. * pow2(std::int16_t(e - 1)) :
0.5 * pow2(std::int16_t(e + 1));
}
或
constexpr double pow2(std::int16_t e)
{
return e == 0 ? 1. :
((e & 1) ? (e > 0 ? 2. : 0.5) : 1.)
* pow2(std::int16_t(e / 2))
* pow2(std::int16_t(e / 2));
}
和
template<bool S , std::int16_t E , std::uint32_t M>
struct number
{
static constexpr const double value = (sign ? -1. : 1.) * M * pow2(E);
};
生活例子
相关文章:
- 在C++中,为什么int可以使用new运算符初始化变量,而double不能
- C++ 类型 'complex<double>' 中类中的复杂初始化不提供调用运算符
- 使用 double 在 C++ 中初始化 int 之间的差异
- 错误:调用'begin(long double [nPoints])'没有匹配函数;使用硬编码的 int 与整数变量初始化向量
- C++:无法使用条件类型在模板函数中使用 'double' 类型的 lvalue 初始化 'char*' 类型的参数
- 错误:初始化时无法将'Vector (*)(double, Vector)'转换为'ForwardEulerSolver*'
- 错误:表达式列表在初始化器[-fpermissive] Double Paycalc(p,yir,y)中被视为复合表达式
- 初始化矢量<矢量的最快方法>大小为 0,容量<double>固定
- 使用 std::uniform_real_distribution 初始化一个 N 大小的 std::vector<double>
- 可能吗?std::vector<double> my_vec(sz);已分配但未初始化或填充
- 错误:没有用于初始化'List<double>::node'的匹配构造函数
- 定义最大双精度时"无法在初始化时将'double (*)() noexcept'转换为'double'"
- 为什么用double&&初始化对象方法不起作用?
- 错误:初始化时无法将'float*'转换为"qreal* {aka double*}"
- 如何使用double[];初始化boost::random::discrete_distribution;
- C++ 犰狳:从 vector<vector 初始化 mat <double>> 破坏数据
- 在编译时初始化double
- 初始化 std::p air<double, std::array<std::p air<double, double>, 3> >
- 初始化矢量<矢量<矢量<double>> >C++
- C:用double初始化对变量的引用