高精度双精度的 Sprintf 格式化问题
sprintf formatting problem for doubles with high precision
所以我最近升级了一个旧的c ++项目,该项目是使用Visual Studio 2012 - Windows XP(v110_xp(平台工具集构建的。在此项目的代码中,有一些非常精确的双重计算恰好需要多达 20 个字符的精度。然后将这些双精度值保存到字符串中,并使用printf
API打印出来。下面是此项目中将发生的情况的示例:
double testVal = 123.456789;
// do some calculations on testVal
char str[100] = { 0 };
sprintf(str, "%.20le", testVal);
在此操作之后,str = "1.23456789000...000e+02",这是预期的。
但是,一旦我更新项目以与Visual Studio 2019兼容,使用Visual Studio 2019(v142(平台工具集和c ++ 17,上述代码就会为str生成不同的输出。 调用sprintf
将值格式化为字符串后,str = "1.23456789000...556e+02"
.这个问题并不局限于这个值,还有更多的聚合问题。例如,sprintf
格式设置后"2234332.434322"
的起始值之一更改为"2.23433324343219995499e+07"
从我读过的所有带有"l"格式代码的文档中,它应该是将长双精度转换为字符串的正确字符。不过,这种行为感觉就像教科书上的浮点>双精度转换。
我尝试将项目浮点模型构建参数设置为精确、严格,然后快速查看这些选项中的任何一个是否有帮助,但它对问题没有影响。
有谁知道为什么会这样?
使用全新的 Ryu (https://github.com/ulfjack/ryu( 或 Grisu-Exact (https://github.com/jk-jeon/Grisu-Exact(,它们比sprintf
快得多,并保证往返正确(以及更多(,或者旧的双转换 (https://github.com/google/double-conversion(,它比其他两个慢,但有相同的保证,仍然比sprintf
快得多,并且经过实战测试。
(免责声明:我是Grisu-Exact的作者。
我不确定你是否真的需要打印出20个十进制数字,因为我个人很少有数字很重要的情况。如果拥有 20 位数字的唯一目的只是为了不损失任何精度,那么上面提到的库肯定会为您提供更好(和更短(的结果。如果由于某些原因,位数必须精确地为 20,那么 Ryu 仍然提供这样的功能(称为 Ryu-printf(,它再次具有往返保证并且比sprintf
快得多。
编辑
为了更详细地阐述最后一句话,请注意,一般来说,如果位数是固定的,则不可能有往返保证,因为,好吧,如果这个固定数字太小,比如说,3,那么就没有办法区分 0.123 和 0.1234。但是,20 足够大,因此真实值的最佳近似值(这是 Ryu-printf 产生的(始终保证是往返正确的。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- C++格式化输出问题
- 高精度双精度的 Sprintf 格式化问题
- 解析格式化输入时划分单词时出现问题
- 格式化c++输出问题