int64_t再次加倍为int64_t,失去精度



我需要解析一个用科学符号表示的给定类型(例如:long-long integer)。示例:

123456789012345678.3e-3
123456789012345678.3

我知道给定字符串的类型,但我不能使用strtoll,因为数字是用科学符号表示的。我所做的是使用strtod转换它,对int64_t进行错误检查,并将其强制转换回int64_t。ErrCheckInt和ErrCheckDouble对整型和浮点型进行错误检查(上溢、下溢等),并将数字强制转换为任何类型。

double res = strtod(processedStr, &end);
return (std::is_floating_point<OUT_T>::value) ? ErrCheckFloat<double, OUT_T>(res, out) : ErrCheckInt<double, OUT_T>(res, out);

问题是,当我用double解析int64_t时,我得到了一个具有正确科学符号的浮点数,1个有效位。当我再次将数字强制转换为int64_t时,我失去了精度。示例编号:

input:             123456789012345678.3
double_converted:  1.23456789012346E+17
cast_to_int64_t:   123456789012345680
expected:          123456789012345678

我知道这个数字足够长,可以用双倍精度正确表示。我可以用长双,但那不能解决问题。

我可以评估字符串,并在最后根据e表示法删除/添加数字,但处理应该非常非常快,因为代码将在嵌入式rtos中运行。我已经做了很多检查,strtod也会慢慢来。

我知道给定字符串的类型,但我不能使用strtoll,因为数字是用科学符号表示的。

您只需要调用一次,使用生成的指针来检测数字是否为xxxeyyy形式,然后再次调用strtoll来解析指数。在我看来,这比浮点运算简单得多。

我知道这个数字足够长,可以用双倍精度正确表示。

不,您不知道,因为您的示例输入是"123456789012345678",在IEEE 754双精度中无法表示。

我可以使用长双,但这不能解决问题。

实际上,如果编译器将long double映射到"具有64位有效位的80位扩展精度",它将解决问题:所有64位整数都可以用该格式表示。GCC和Clang在Linux上通过long double提供了历史上的80位浮点格式,但这非常不方便,以至于在Windows上实际上被认为是不可用的(您需要更改FPU控制字,并在每次有库函数要调用时恢复它,并编写自己的数学函数来操作80位浮点值。从strtold开始。

相关内容

  • 没有找到相关文章

最新更新