首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TRUNC会导致0小数的错误值。

问TRUNC会导致0小数的错误值。
EN

Stack Overflow用户
提问于 2015-07-03 11:28:48
回答 1查看 610关注 0票数 2

当我寻找下面的情况时,我没有找到答案。我有一个简单的值被四舍五入为0小数。我在oracle中尝试下面的查询,并获得如下所示:

代码语言:javascript
复制
select 1 / 3 * 19608 CORRECT from dual;
--6536 is correct

select TRUNC(1 / 3 * 19608, 0) WRONG from dual;
 --6535 which is wrong

select TRUNC(1 / 3 * 19608, 2) WRONG from dual;
 --6535.99 which is wrong

请让我知道你是否有与这种情况有关的问题。

更新

很抱歉拒绝了你的回答。我发现还有一个问题你的回答仍然无效:

代码语言:javascript
复制
select TRUNC(1 / 3 * 15, 0) WRONG from dual;
--5 is correct

小数字我得到的数字是正确的。这也是我所期望的,因为19608会导致错误的数值。19608是幻数吗?

更新2

我理解在下面的答案中所解释的数学。但我仍然对甲骨文TRUNC的功能表示怀疑,因为它没有像预期的那样提供正确的输出。现在,我想举例说明这一点,如下所示:

代码语言:javascript
复制
SELECT ( (4500 + ROWNUM) * 3) multiple_3,
       TRUNC (1 / 3 * ( (4500 + ROWNUM) * 3), 2) result_with_trunc,
       1 / 3 * ( (4500 + ROWNUM) * 3) no_trunc
  FROM DUAL CONNECT BY 4500 + ROWNUM < 6000

在上面的SQL中,您可以检查结果;准确地说,在500行之后,甲骨文的行为与可被3整除的数字不同。如果下面的答案是正确的,则意味着15000完全可以被3整除,而15003是而不是完全可以被3整除。

我希望这是有意义的,这与任何数学无关。

更新3

一个简单而直接的问题如下:

代码语言:javascript
复制
SQL> set numwidth 50
SQL> SELECT TRUNC(1 / 3 * 15000, 50) FROM dual;

                               TRUNC(1/3*15000,50)
--------------------------------------------------
                                              5000

SQL> SELECT TRUNC(1 / 3 * 15003, 50) FROM dual;

                               TRUNC(1/3*15003,50)
--------------------------------------------------
         5000.999999999999999999999999999999999999

为什么我的oracle客户端(11.2.0.1.0)和服务器(11g 11.2.0.4.0 -64位)对一个可以被3整除的数字给出了不同的结果?

上一次更新-接受应答

@Lalit Kumar B谢谢你强调重复的十进制数。我遇到的情况不是先知的错。警报器正在正常工作。问题是0.3333.分数乘以一个可以被3整除的数,但不是完全的。这样的数字很少有300,15003,等等,

因此,当将ORACLE函数应用于1/ 3 *X乘法所产生的小数时,其结果是正确的,其中X不能完全被3整除。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-03 11:38:27

查询和输出都没有问题。您的客户端是第一个查询输出中值的舍入。

代码语言:javascript
复制
SQL> SELECT TRUNC(1 / 3 * 19608, 50) FROM dual;

TRUNC(1/3*19608,50)
-------------------
               6536

SQL> set numwidth 50
SQL> SELECT TRUNC(1 / 3 * 19608, 50) FROM dual;

                               TRUNC(1/3*19608,50)
--------------------------------------------------
         6535.999999999999999999999999999999999999

SQL>

在我的SQL*Plus客户机中,我调整了数字宽度,您可以看到实际值。

此外,在甲骨文中,scale对于数字数据类型有限制,可以达到100%的准确性。这个限制是38位数字,你不能100%的准确地发布。您需要理解尾数、和指数。在这种情况下,scale对指数的可能最小值设置了一个限制。

更新 OP更新了这个问题。

选择TRUNC(1 /3* 15,0)从对偶错误;-5是正确的

与甲骨文无关。它是纯mathematics.15完全可以被3整除,因此得到一个整数 5。

19608是幻数吗?

19608不是完全可除的被3,您将有小数部分。我已经展示了上面的内容。(1/3)*19608的正确结果是而不是 6536。正确的结果是6535.9和循环的十进制。它永远不会被3整除。

更新2 OP更新了这个问题。

代码语言:javascript
复制
SQL> set numwidth 50
SQL> SELECT (1/3)*5000*3 FROM dual;

                                      (1/3)*5000*3
--------------------------------------------------
         5000.000000000000000000000000000000000001

SQL> SELECT (1/3)*(5000*3) FROM dual;

                                    (1/3)*(5000*3)
--------------------------------------------------
                                              5000

SQL> SELECT trunc((1/3)*(5000*3),2) FROM dual;

                           TRUNC((1/3)*(5000*3),2)
--------------------------------------------------
                                              5000

SQL> SELECT 1 / 3 * 15003 FROM dual;

                                         1/3*15003
--------------------------------------------------
         5000.999999999999999999999999999999999999

SQL> SELECT 15003/3 FROM dual;

                                           15003/3
--------------------------------------------------
                                              5001

上述对类似(,而非相同的)操作的查询结果不同的原因是,Oracle从左到右计算。

当您执行1/3*n时,Oracle的计算结果与n/3不同。在前一种情况下,首先计算1/3,从而创建一个recurring non-terminating decimal number 0.3333....,其中3是递归数字。现在,当你用一个3的倍数乘以它时,它已经失去了的精度,因此最终的结果也将是循环的非终止数。

当您将其放入大括号中时,您要求Oracle显式地计算大括号内的部分,而不仅仅是从左到右。因此,下面两个是在中不以相同方式计算的:

代码语言:javascript
复制
1 / 3 * 15003

的计算方法与

代码语言:javascript
复制
15003/3
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31205778

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档