This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器/TMS320F28388D:字符串和浮点值之间的转换

Guru**** 2966500 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/940004/compiler-tms320f28388d-conversions-between-strings-and-floats

器件型号:TMS320F28388D

工具/软件:TI C/C++编译器

在字符串和浮点值之间转换时、使用带有%f 格式的 strtof 和 snprintf 时、我们会看到一些意外行为。 我们将针对 CM 上的 ARM 使用 ti-cgt-C2000_20.2.TLS 库。  

STRT:

如果输入字符串15.000、则转换正常、但如果输入15.0000000000000000、则得到15.000005。 当单步执行第170行的例程时,Result*base 会变大,并且向该值中添加0实际上会增加非零量。 N + 0不再等于 N? 我想当底座为1e9或1e10时、它就在附近。 15.000000000000000000000000只有两个有效位、可以在浮点中轻松表示、没有错误、但 strtof 不会在没有为大量零添加错误的情况下进行转换。  

作为一种解决方案、我们使用 strtod 将问题进一步移出可能不会成为问题的地方。 strtod 不会错误地正确转换15.00000000。  

snprintf:

snprintf (valueStr、23、"%.6F"、msg->val.valueef);

当输入的浮点值为123456790519087104  (0x5bdb4da6)时,打印的字符串为 123456790519087076.187。 这是意料之外的。 我们尝试使用%.6lf 并将浮点数转换为双精度型、但这没有解决 strtod 情况中的问题。  

是否有任何关于可能导致这种情况的想法? 必须正确显示输入的数字、或者至少可以正确显示哪些数字、以及在这种情况下不显示这些数字的原因。

谢谢、

Jennifer

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您将此问题通知我们。  我可以重现相同的结果。  我提交了 EXT_EP-10042条目 以进行调查。  欢迎您使用我签名中的以下链接进行操作。

    谢谢、此致、

    乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    此处的基本问题是浮点数字具有二进制格式、十进制和二进制浮点之间的转换具有相当多的" gotchas"。

    要了解这里发生的情况、您需要意识到(例如) 15e8恰好是0x59682f00。 现在、32位浮点只有24位精度、因此我们已经将几乎所有的精度都与整数部分结合使用。 采用代数方法、15e9恰好是0x37e11d600、超过了32位浮点的精度。 在32位浮点中、我们可以做得最好的是0x37e11d400、即149999488、或0x37e11d800、即15000000512。 当小数点恰好位于数字的"15"部分之后时、情况也是如此;只有二进制表示中的有效位数才有意义。 乍一看、如果15完全可以表示、那么添加更多的零仍然会提供一个可表示的数字、但情况并非如此、原因很简单、10不是2的幂。 乘以 除2的幂以外的任何值都会增加表示确切值所需的二进制数字的数量。

    您在 strtof 的源代码中看到的是从字符串中累积浮点值的直接方法:对于从左到右的每个数字、将您拥有的数字乘以10并添加新数字、并且仅在最后时刻设置指数。 也就是说、我们计算出15、000、000、000除以10亿。 您可以看到这是如何处理上述舍入问题的。 将算法更改为将加法器除以不断增加的10的幂、会产生相同的问题、只有在小数点右侧的某个位置。  结果对本示例更好、但对其他示例更好。

    事实证明、从十进制浮点到二进制浮点的转换很困难、反之亦然。  要从 strtof 获得最佳答案(将整个字符串视为一个)、需要非常复杂的数字方法。 为了更快地计算结果、我们的实现消除了这些方法。

    如果精确值很重要、则应考虑以十六进制浮点常量的形式表示所有浮点常量。  由于这种常量是二进制格式、因此不存在舍入问题、因为存在十进制到二进制的转换。  您可以使用%a 转换打印十六进制浮点数字。  例如、123456790519087104恰好是0x1.b69b4cp+56