【问题标题】:C++ typecast doubleC++ 类型转换双精度
【发布时间】:2016-01-25 00:01:45
【问题描述】:

C++ 中有没有办法将 double double typecast 转换成 float, int32 em>、uint8bool 没有 丢失信息?如果不能返回错误呢?

编辑: 其实我还不够清楚……

我有一个函数,它以 doubletype 为参数。 这个函数应该检查我是否可以将 double 类型转换为 type 而不会丢失信息。

bool check_type(double value, enumType type)
{
    switch(type) {
        case enum_uint8:
            return "check wheter value can be typecasted to type"
            break;
        case enum_float:
             .
             .
             .
    }
    return false;
}

【问题讨论】:

  • 一个类似的问题:你能不能只用一个比特来表示两个比特的状态而不丢失信息?
  • 您可以随时进行投射、投射和比较。
  • @DavidSchwartz 但这只是重新解释/输入双关语。 float/int32 等值将被视为无意义或依赖于实现
  • Boost 中实现了一些错误检查。 boost.org/doc/libs/1_60_0/libs/numeric/conversion/doc/html/…

标签: c++ casting type-conversion


【解决方案1】:

没有。这就像烧掉你的狗,这样你就可以把它放在一个骨灰盒里,以便更方便地搬家,然后当你发现你无法将它解开时表现得非常惊讶。

如果转换有丢失数据的风险(这称为“缩小转换”),您通常会收到编译器警告,但由于这取决于初始值,这些初始值通常仅在运行时才知道,你无法为它获得编译器错误……而且 C++ 的“轻量级”范式阻止语言设计者让你的程序在运行时抛出异常或其他任何东西。

【讨论】:

  • @erip: 可怜的东西 :(
【解决方案2】:

也许可以试试这样的:

#include <limits>

template<typename T>
inline bool is_in_allowed_range(double value)
{
    return (
        (value >= static_cast<double>(std::numeric_limits<T>::min())) &&
        (value <= static_cast<double>(std::numeric_limits<T>::max()))
    );
}

bool check_type(double value, enumType type)
{
    switch(type) {
        case enum_uint8:
            return is_in_allowed_range<uint8>(value);
        case enum_float:
            return is_in_allowed_range<float>(value);
        ...
    }
    return false;
}

...

double value = ...;
if (check_type(value, enum_uint8))
{
    uint u = static_cast<uint8>(value);
    // use u as needed ...
}

或者更简单:

#include <limits>

template<typename T>
bool convert_to_type(double value, T *arg)
{
    if ((value >= static_cast<double>(std::numeric_limits<T>::min())) &&
        (value <= static_cast<double>(std::numeric_limits<T>::max())))
    {
        *arg = static_cast<T>(value);
        return true;
    }
    return false;
}

...

double value = ...;
uint8 u;
if (convert_to_type(value, &u))
{
    // use u as needed...
}

【讨论】:

  • 将双精度数转换为浮点数通常会丢失信息(精度),即使该值落在浮点值范围内。范围检查不足以保证无损转换。
  • @IInspectable: 是的,但是你对浮点数所做的任何事情通常都是相当有损的。
【解决方案3】:

由于double 使用比float 更多的位来存储数据,如果您将double 存储在float 中,则数据有可能不适合float 的大小。因此,您会丢失一些数据。

由于int32uint8 仅存储整数值,C++ 中的双精度数存储为(1 位符号)+2^(11 位指数)1(52 位有效) ,共 64 位。因此,您很可能会丢失数据。 [这取自评论]

但投射是可能的。

顺便说一句,您可以通过检查 double 中的值是否大于您要转换的数据类型的最大限制来生成错误。

【讨论】:

  • 在 int 类型中存储 double 是不准确的。 C++ 中的双精度数存储为 (1 位符号)+2^(11 位指数)*1*(52 位有效位),总共 64 位。这意味着它不安全,因为您不是存储文字数字,而是计算字段
  • @ByrenHiggin:C++ 转换不是按位复制/截断操作。他们知道如何将 IEEE 浮点数转换为二进制补码(事实上,这正是拥有类型系统的初衷)。而 literals 与此完全正交。
  • 是的,@ByrenHiggin 你是对的。我将此添加到我的答案中。
  • @MASh:拜伦是不对的。 double-to-integer 转换没有什么“不安全”的地方,除非我们当然要计算双重存储信号 NaN 表示的可能性!
  • @MASh:除了我已经说过的内容之外,没有什么可以解释的了。拜伦需要解释他的观点。或者也许您可以向我解释一下,因为您已经将它纳入您的答案。
【解决方案4】:

可以将 double 类型转换为 float,但您会遇到数字四舍五入的情况,因此它不会准确到之前的数字。双精度数不能安全地放入整数相似类型或布尔值。

如果您在运行时进行检查,则无法在基本 C++ 中获取变量类型,但如果您在编译时进行检查,则可以使用 variable::typeid 进行检查。检查信息丢失的选项是将一种方式转换为所需的类型,然后转换回以前的类型,然后比较结果以查看信息是否丢失

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多