为什么 pg_size_pretty 返回负值?
我正在使用 pg_size_pretty() ,我发现当我传递一个很大的值时,它开始返回负值。 这是我的测试:
select pg_size_pretty(9223370000000000000); -- "8388606 TB"
select pg_size_pretty(9223371000000000000); -- "8388607 TB"
select pg_size_pretty(9223372000000000000); -- "-8388607 TB"
你能解释一下为什么吗? 谢谢。
I was playing with pg_size_pretty() and I've discovered that when I pass it a great value it starts to return negative value.
This is my test:
select pg_size_pretty(9223370000000000000); -- "8388606 TB"
select pg_size_pretty(9223371000000000000); -- "8388607 TB"
select pg_size_pretty(9223372000000000000); -- "-8388607 TB"
Can you explain me why?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
最高的有符号 64 位 int 是 922337203685477587。这仅比所讨论的数字多一点点。肯定是
pg_size_pretty
中的某个地方存在溢出。根据评论中提到的代码,
pg_size_pretty
正在尝试对数字进行舍入,并使用大于最大有符号 64 位 int 的中间值来实现此目的。 9223372000000000000 + 1024*1024*1024*1024/2 = 9223372549755813888,大于 922337203685477587。更新:添加了第二段并澄清溢出不在调用方中。
The highest signed 64 bit int is 922337203685477587. That's but a tiny bit more than the number in question. Surely there's an overflow somewhere in
pg_size_pretty
.Based on the code mentioned in a comment,
pg_size_pretty
is attempting to round the number and does so using an intermediary value that's larger than the max signed 64-bit int. 9223372000000000000 + 1024*1024*1024*1024/2 = 9223372549755813888, which is larger than 922337203685477587.Update: Added second paragraph and clarified that the overflow isn't in the caller.
你没有溢出,
pg_size_pretty
正在溢出。pg_size_pretty
函数应该采用bigint
:并且
9223372000000000000
9223372000000000000
9223372036854775808
所以9223372000000000000
是一个完全有效的bigint
并且pg_size_pretty
应该用它做正确的事情。您应该向 PostgreSQL 人员报告错误并赢得荣誉。更新:检查 PostgreSQL 源代码(感谢 Jeremiah Peschka 提供链接)向我们展示了错误所在:
如果
size
接近int64 的限制
,然后向其添加mult/2
将会溢出,然后再除以mult
使其回到范围内。You are not overflowing,
pg_size_pretty
is overflowing. Thepg_size_pretty
function is supposed to take abigint
:And
9223372000000000000 < 9223372036854775808
so9223372000000000000
is a perfectly validbigint
andpg_size_pretty
should do The Right Thing with it. You should report a bug to the PostgreSQL people and win kudos.UPDATE: Examining the PostgreSQL source code (thanks to Jeremiah Peschka for providing the link) shows us where the bug is:
If
size
is close to the limit ofint64
, then addingmult/2
to it will overflow before the following division bymult
can bring it back into range.