选择十进制形式的浮点数

Posted

技术标签:

【中文标题】选择十进制形式的浮点数【英文标题】:Selecting floating point numbers in decimal form 【发布时间】:2013-09-18 10:05:10 【问题描述】:

我在 PostgreSQL 表中有一个小数:

test=# CREATE TABLE test (r real);
CREATE TABLE
test=# INSERT INTO test VALUES (0.00000000000000000000000000000000000000000009);
INSERT 0 1

当我运行以下查询时,它返回的数字为8.96831e-44

test=# SELECT * FROM test;
      r      
-------------
 8.96831e-44
(1 row)

如何以十进制形式 (0.00000000000000000000000000000000000000000009) 而非科学计数法显示 psql 中的值?我也会对0.0000000000000000000000000000000000000000000896831 感到满意。不幸的是,我无法更改表格,而且我并不真正关心精度损失。

(我和to_char玩了一段时间没有成功。)

【问题讨论】:

啊,看到它是真的。这是一个浮点表示......你永远不会得到这个值:What Every Computer Scientist Should Know About Floating-Point Arithmetic @ppeterka66: 这是real (postgresql.org/docs/9.1/static/datatype-numeric.html) 更新了我的答案:这似乎是一个已知问题,而且我感觉不对... 【参考方案1】:

Real in Postgres 是浮点数据类型,存储在 4 个字节上,即 32 位。

你的价值,

0.00000000000000000000000000000000000000000009

不能用 32 位 IEEE754 浮点数精确表示。您可以检查确切的值in this calculator

你冷尝试使用双精度(64位)来存储它,根据计算器,这似乎是一个精确的表示。 不正确 Patricia 表明它只是对值进行四舍五入的计算器,即使明确要求它不要... Double 意味着更精确,但仍然没有确切的值,因为这个数字不能用有限数量的二进制表示位数。 (谢谢,Patricia,吸取的教训(再次):不要相信您在 Intertubez 上看到的内容)

一般情况下,您应该使用 NUMERIC(precision, scale) 格式,这样可以精确存储数字以获取正确的值。

但是,对于精确的十进制表示,您要存储的值似乎比 postgres 允许的(似乎是 30)更大。如果您不想进行计算,只需存储它们(我承认这不是很常见的情况),您可以尝试将它们存储为字符串......(但这很难看......)

编辑

这个to_char问题好像是known bug...

引用:

我对此的直接反应是 float8 值没有 57 位 的精度。如果您期望该格式字符串执行某些操作 有用,您应该将其应用于数字列而不是双精度列 精度一。

我们可能会设法解决这个特殊的案例 正如你所期待的,但总会有相似的外观 由于精度不存在而无法工作的情况。

快速查看代码,您得到“0”的原因。是不是 在 15 位数字后四舍五入以确保它不会打印垃圾。也许 对于价值非常小的情况,它可能会更聪明一些 大于 1,但这不会是一个简单的变化。

(from here)

但是,我认为这无可辩驳。恕我直言,如果值适合类型...

推荐阅读:

What Every Computer Scientist Should Know About Floating-Point Arithmetic Postgres numeric types BUG #6217: to_char() gives incorrect output for very small float values

【讨论】:

0.00000000000000000000000000000000000000000009 没有精确的表示为有限长度的二进制扩展,因此不可能用双精度表示。最近双是8.999999999999999701371399759001187751098450398312665851146155700922553097223778373253413973215499304719454149066593107164635512162931263446807861328125E-44。由于四舍五入,它可能“看起来”准确。 @PatriciaShanahan 你是对的...天哪,我信任的 IEEE754 计算器即使我将其设置为不舍入值也会舍入...我讨厌这样的时刻... 我用来获取双精度值的技巧是用 Java 编写一个程序,该程序使用双精度值构造一个 BigDecimal 并打印它。 double 到 BigDecimal 的转换是精确的,BigDecimal 的 toString 会产生它拥有的所有数字。 @PatriciaShanahan 可悲的是我知道 - 我最近非常深入地参与了它的工作原理以及 Double.toString 如何运作的复杂性,但黄色警告灯亮着我对二进制表示的有限性一头雾水,我决定相信我所看到的,然后继续写一些完全不正确的东西......

以上是关于选择十进制形式的浮点数的主要内容,如果未能解决你的问题,请参考以下文章

实验2

急求十六进制转浮点数C程序!!!

为啥不使用基于二进制补码的浮点数?

在python中将指数形式的数字转换为十进制形式[重复]

python的浮点数运算是否精度有问题阿

浮点数的十六进制表示