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
我知道这个数字足够长,可以用双精度正确表示。我可以使用 long double 但这不能解决问题。
我可以评估字符串并在最后删除/添加关于 e 符号的数字,但处理应该非常非常快,因为代码将 运行 在嵌入式 rtos 中。我已经做了很多检查,strtod 也会慢慢来。
I know the type of the given string but I can't use strtoll since number is given in scientific notation.
只需要调用一次,使用结果指针检测数字是否为xxxeyyy形式,再次调用strtoll
解析指数。在我看来比通过浮点数简单得多。
I know that number is long enough to be represented correctly with double precision.
不,您不知道,因为您的示例输入是“123456789012345678”,这在 IEEE 754 双精度中是不可表示的。
I can use long double but that won't solve the problem.
实际上,如果您的编译器将 long double
映射到“具有 64 位有效数的 80 位扩展精度”,它 将 解决问题:所有 64 位整数以该格式表示。 GCC 和 Clang 通过 Linux 上的 long double
使历史上的 80 位浮点格式可用,但它非常不方便,以至于实际上被认为在 Windows 上不可用(您需要更改 FPU 控制字,并在每次调用库函数时恢复它,并编写自己的数学函数来对 80 位浮点值进行运算。从 strtold
.
开始
我需要解析以科学记数法表示的给定类型(例如: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
我知道这个数字足够长,可以用双精度正确表示。我可以使用 long double 但这不能解决问题。
我可以评估字符串并在最后删除/添加关于 e 符号的数字,但处理应该非常非常快,因为代码将 运行 在嵌入式 rtos 中。我已经做了很多检查,strtod 也会慢慢来。
I know the type of the given string but I can't use strtoll since number is given in scientific notation.
只需要调用一次,使用结果指针检测数字是否为xxxeyyy形式,再次调用strtoll
解析指数。在我看来比通过浮点数简单得多。
I know that number is long enough to be represented correctly with double precision.
不,您不知道,因为您的示例输入是“123456789012345678”,这在 IEEE 754 双精度中是不可表示的。
I can use long double but that won't solve the problem.
实际上,如果您的编译器将 long double
映射到“具有 64 位有效数的 80 位扩展精度”,它 将 解决问题:所有 64 位整数以该格式表示。 GCC 和 Clang 通过 Linux 上的 long double
使历史上的 80 位浮点格式可用,但它非常不方便,以至于实际上被认为在 Windows 上不可用(您需要更改 FPU 控制字,并在每次调用库函数时恢复它,并编写自己的数学函数来对 80 位浮点值进行运算。从 strtold
.