繁体   English   中英

int64_t再次加倍到int64_t,精度损失

[英]int64_t to double to int64_t again, loss of precision

我需要解析一个用科学记数法表示的给定类型(例如: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开始。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM