了解 Oracle 中 remainder() 函数的行为
Understanding behavior of remainder() function in Oracle
根据余数 (n2,n1) 函数 (https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions133.htm) 的 Oracle 文档,余数 (n2,n1) 函数的计算结果为 = n2 - n1 * N,其中 N = ROUND(n2/n1) 和 n1 != 0.
所以,我希望余数 (10,4) 到 return -2 使用上面记录的计算余数的方法,如下所示:
REMAINDER(10,4)
=10 - 4 * N where N = ROUND(10/4)
=10 - 4 * 3 since ROUND(10/4) = 3
=10 - 12
=-2
但是,运行 Oracle 10g、11g 和 12c 中的 remainder(10,4) returns 2 而不是 -2。
有人可以解释为什么余数 (10,4) 没有按照 oracle 如何计算余数的记录方法进行计算吗?
附加信息:此行为每隔 n2 发生一次,其中 n2 是 n1 / 2 的倍数。可以通过 运行 以下 SQL 验证,其中每个余数函数值应与旁边的值。但它只匹配 n2 的所有其他值。
运行 SQL:
select
remainder(2,4), 2-4*round(2/4),--OUTPUT:2, -2
remainder(6,4),6-4*round(6/4), --OUTPUT: -2, -2
remainder(10,4),10-4*round(10/4),--OUTPUT: 2, -2
remainder(14,4),14-4*round(14/4)--OUTPUT: -2, -2
from dual
编写文档的人(他们似乎不记得数学中的一些定义)自己似乎不确定他们写的是什么。一方面,在解释的早期他们确实提到了 ROUND
- 但后来当他们给出更正式的定义时他们说
•If n1 != 0, then the remainder is n2 - (n1*N) where N is the integer
nearest n2/n1
"Integer nearest" 在算术中没有正式定义,实际上允许将那个名称用于 round(x),除非 x 的小数部分正好是 0.5,在这种情况下 "integer nearest"是模棱两可的,人们可以选择使用 "round down" 作为他们自己对 "integer nearest."
的定义
如果可以的话,不要对文档中的此类不一致感到太生气。你会看到更多。
但是:更糟糕的是行为不一致。我使用的是 Oracle 12.1,在我的机器上我刚刚试了一下,我得到了
remainder(10, 4) = 2
remainder( 6, 4) = -2
无韵无理。使用 FLOOR 等进行自己的划分要好得多。
编辑 - 或者可能有一些原因;也许他们使用 "nearest integer" 的定义来表示,在平局的情况下,最接近的 even 整数。仍然产生意想不到的结果,最好不要使用 Oracle 的 REMAINDER() 函数。
根据余数 (n2,n1) 函数 (https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions133.htm) 的 Oracle 文档,余数 (n2,n1) 函数的计算结果为 = n2 - n1 * N,其中 N = ROUND(n2/n1) 和 n1 != 0.
所以,我希望余数 (10,4) 到 return -2 使用上面记录的计算余数的方法,如下所示:
REMAINDER(10,4)
=10 - 4 * N where N = ROUND(10/4)
=10 - 4 * 3 since ROUND(10/4) = 3
=10 - 12
=-2
但是,运行 Oracle 10g、11g 和 12c 中的 remainder(10,4) returns 2 而不是 -2。
有人可以解释为什么余数 (10,4) 没有按照 oracle 如何计算余数的记录方法进行计算吗?
附加信息:此行为每隔 n2 发生一次,其中 n2 是 n1 / 2 的倍数。可以通过 运行 以下 SQL 验证,其中每个余数函数值应与旁边的值。但它只匹配 n2 的所有其他值。 运行 SQL:
select
remainder(2,4), 2-4*round(2/4),--OUTPUT:2, -2
remainder(6,4),6-4*round(6/4), --OUTPUT: -2, -2
remainder(10,4),10-4*round(10/4),--OUTPUT: 2, -2
remainder(14,4),14-4*round(14/4)--OUTPUT: -2, -2
from dual
编写文档的人(他们似乎不记得数学中的一些定义)自己似乎不确定他们写的是什么。一方面,在解释的早期他们确实提到了 ROUND
- 但后来当他们给出更正式的定义时他们说
•If n1 != 0, then the remainder is n2 - (n1*N) where N is the integer nearest n2/n1
"Integer nearest" 在算术中没有正式定义,实际上允许将那个名称用于 round(x),除非 x 的小数部分正好是 0.5,在这种情况下 "integer nearest"是模棱两可的,人们可以选择使用 "round down" 作为他们自己对 "integer nearest."
的定义如果可以的话,不要对文档中的此类不一致感到太生气。你会看到更多。
但是:更糟糕的是行为不一致。我使用的是 Oracle 12.1,在我的机器上我刚刚试了一下,我得到了
remainder(10, 4) = 2
remainder( 6, 4) = -2
无韵无理。使用 FLOOR 等进行自己的划分要好得多。
编辑 - 或者可能有一些原因;也许他们使用 "nearest integer" 的定义来表示,在平局的情况下,最接近的 even 整数。仍然产生意想不到的结果,最好不要使用 Oracle 的 REMAINDER() 函数。