当我搜索下面的情况时,我没有找到答案。我有一个简单的值舍入到0小数。我在oracle中尝试下面的查询,得到如下所示:
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
如果您有与此情况相关的问题,请与我们联系。
更新
很抱歉拒绝您的回答。我发现了一个问题,你的答案仍然无效:
select TRUNC(1 / 3 * 15, 0) WRONG from dual;
--5 is correct
我为小数字得到了正确的数字。我也期望错误,因为19608会导致错误的价值观。 19608年是一个神奇的数字吗?
更新2
我理解数学在下面的答案中解释。但是我仍然怀疑oracle TRUNC函数没有按预期给出正确的输出。现在,我想通过以下示例来说明这一点:
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行之后,oracle的行为与可被3整除的数字不同。 如果以下答案为真,则表示15000完全可被3整除,15003 不完全可被3整除。
我希望这有点意义,这与任何数学无关。
更新3
一个简单直接的问题可以如下:
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-64bit)对可被3整除的数字的相同操作给出不同的结果?
最后更新 - 接受的答案
@ Lalit Kumar B感谢您对重复的十进制数字施加压力。 我遇到的情况不是oracle的错。 trunc正在正常工作。 问题是0.3333 ....分数乘以可被3整除但不完全的数字。这些数字的例子很少是300,15003等,
因此,当应用于乘以1/3 * X得到的分数时, ORACLE TRUNC FUNCTION 的结果是正确的,其中X不能完全被3整除。
答案 0 :(得分:4)
查询没有问题,输出也没有问题。它是 客户端 ,它会在您的第一个查询输出中对该值进行四舍五入。
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 客户端中,我调整了 numwidth ,您可以看到实际值。
此外,在Oracle中, NUMBER数据类型的比例限制为100%准确度。而且这个限制是38位数,你不能100%准确。您需要了解尾数和指数。在这种情况下,比例会对指数的可能最小值设置限制。
更新 OP更新了问题。
从双选择TRUNC(1/3 * 15,0)WRONG; --5是正确的
与Oracle无关。这是纯粹的数学。 15
完全可以归3
,因此您会得到整数 5
。
{p>19608是一个神奇的数字吗?
19608
<{1}} 3
的正确结果是不 (1/3)*19608
。正确的结果是6536
重复小数。它永远不会被3整除。
更新2 OP更新了问题。
6535.9
上述查询类似(不相同)操作的结果不同的原因是Oracle从左到右进行评估。
执行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
的方式对其进行评估。在前一种情况下,首先评估n/3
,从而创建 recurring non-terminating decimal number 1/3
,其中0.3333....
是重复数字。现在,当您将其乘以3
的倍数时,它已经丢失了精度,因此最终结果也将是重复的非终止数字。
当你把它放在大括号内时,你要求Oracle明确评估大括号内的部分,而不是从左到右。因此,在Oracle中,以下两个未评估的方式相同
3
的评估方式与
的评估方式不同1 / 3 * 15003