为啥 "%.10f" % Decimal(u) 可以发出带有文字冒号的字符串?

Posted

技术标签:

【中文标题】为啥 "%.10f" % Decimal(u) 可以发出带有文字冒号的字符串?【英文标题】:Why can "%.10f" % Decimal(u) emit a string with a literal colon?为什么 "%.10f" % Decimal(u) 可以发出带有文字冒号的字符串? 【发布时间】:2018-02-02 21:44:40 【问题描述】:

格式化要打印的数字时,12 位数字将在点后紧跟冒号进行格式化。为什么会这样?这是 AIX 系统上的 Python 2.7。

$ uname -a ; /opt/bin/python2.7
AIX myserver 1 6 00F6A5CC4C00
Python 2.7.12 (default, Sep 29 2016, 12:02:17) [C] on aix5
Type "help", "copyright", "credits" or "license" for more information.
>>> '0:.10f'.format(123456789012)
'123456789011.:000000000'
>>> from decimal import Decimal
>>> u=123456789012
>>> print "%.10f" % Decimal(u)
123456789011.:000000000

更多信息:

不是每个12位数字:

>>> for x in range(123456789010,123456789020):
...     print '0:.10f'.format(x)
...
12345678900:.0000000000
123456789010.:000000000
123456789011.:000000000
123456789013.0000000000
123456789013.:000000000
123456789015.0000000000
123456789016.0000000000
123456789017.0000000000
123456789017.:000000000
123456789019.0000000000

这不会发生在任何其他长度数字上。另外,我尝试了 bash 和 perl 的 printf,但它们都没有发生这种情况。

这里发生了什么?

根据要求,这里是screen shot video。

更多信息:

>>> import locale
>>> locale.getdefaultlocale()
('en_US', 'ISO8859-1')

user2357112 pastebin 代码的结果:

>>> import ctypes
>>> f=ctypes.pythonapi.PyOS_double_to_string
>>> f.argtypes=ctypes.c_double,ctypes.c_char,ctypes.c_int,ctypes.c_int,ctypes.POINTER(ctypes.c_int))
>>> f.restype=ctypes.c_char_p
>>> print f(123456789012.0, 'f', 10, 0, None)
123456789011.:000000000

Antti_Happa 的 pastebin 正确打印了所有数字。

使用格式 r 给出:

print 'e: 0:.10e\nf: 0:.10f\ng: 0:.10g\nr: 0:0r'.format(x)
ValueError: Unknown format code 'r' for object of type 'int'

使用 e、f 和 g 格式提供以下内容:

for x in range(123456789000,123456789019):
print 'e: 0:.10e\nf: 0:.10f\ng: 0:.10g'.format(x)
e: 1.2345678900e+11
f: 123456789000.0000000000
g: 1.23456789e+11
e: 1.2345678900e+11
f: 123456789000.:000000000
g: 1.23456789e+11
e: 1.2345678900e+11
f: 123456789001.:000000000
g: 1.23456789e+11
e: 1.2345678900e+11
f: 123456789003.0000000000
g: 1.23456789e+11

我无权在此服务器上安装或更新任何内容。我可以请求更新版本,但这种性质的更改请求需要相当长的时间。此外,其他程序依赖于此安装,需要进行大量测试。

我被告知只有 IBM 提供的包会被安装,并且 IBM 提供的最新的 python 2.7 包是 2.7.12。

我已经“解决”了这个问题

othervar = '0:.10f'.format(somevar).replace(':', '0')

这非常不安全,我知道,但是...... 耸耸肩

啊!我刚刚注意到一个错误……123456789012 被格式化为少一:123456789011.:0000000000……这是一个奇怪的错误。

【问题讨论】:

无法在任何 python 版本上重现。 我们通常不会要求这个,但是你能发布这个行为的截图吗? 请提供locale.getdefaultlocale()的输出。 对于其他想要深入了解源代码的人,here's 2.7.12 Python 源代码树。我怀疑这个问题最终可能会追溯到 Python 依赖的一些基本库例程的 AIX 实现中的错误。 : 字符出现在 ascii 中 9 之后。事实上,如果您将这些 : 视为在数字上等同于该位置的 10,则输出在技术上是正确的。 【参考方案1】:

虽然不是“答案”,但我可以为您提供在 AIX 上运行的稍新版本的结果。

抱歉,我无法重现您的问题。

[lholtscl@ibm3 ~]$ python
Python 2.7.13 (default, Sep  7 2017, 21:08:50) [C] on aix7
Type "help", "copyright", "credits" or "license" for more information.
>>> print "%.10f" % 123456789012
123456789012.0000000000
>>> '0:.10f'.format(123456789012)
'123456789012.0000000000'

【讨论】:

谢谢。我实际上可以使用您的评论来推动更新 python。

以上是关于为啥 "%.10f" % Decimal(u) 可以发出带有文字冒号的字符串?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 settings.split 返回 "" 而不是 <f:debug> 显示的预期数组值?

一个计算c语言下的if语句的练习题,提示数据转换出错,打括号出错,为啥?

为啥即使另一个活动在顶部,launchMode="singleTask" 的启动器活动总是被推到后台堆栈的顶部? [复制]

bat 脚本 for /f "delims=", delims的使用

我用的是thinkphp3.2.3为啥使用jquery的ajax接收不到post值

为啥用Visual Studio给CUDA编程,却显示"undeclared identifier"呢