OpenEdge abl truncate(log(4)/ log(2))应该是2返回1

时间:2013-10-02 14:34:59

标签: math floating-point progress-4gl openedge

我有一个问题,我猜是OpenEdge ABL / Progress 4GL中浮点的舍入错误

display  truncate(log(4) / log(2) , 0) .

这会返回1.0,但应该给我一个2.0

如果我做这个伪解决方案,它在大多数情况下给出了正确答案,提示浮点数。

display  truncate(log(4) / log(2)  + 0.00000001, 0) .

我所追求的是这个

find the largest x where 

p^x < n, p is prime, n and x is natural numbers.

=>

x = log(n) / log(p)

对此有什么看法?

4 个答案:

答案 0 :(得分:2)

没有数值算术系统。 4和2的自然对数无法准确表示。由于log函数只能返回可表示的值,因此它返回精确数学结果的近似值。

有时这种近似值会略高于数学结果。有时它会略低一些。因此,您通常不能指望log(x*x)恰好两倍log(x)

理想情况下,高质量的log实现将返回最接近精确数学值的可表示值。 (这被称为“正确舍入”的结果。)在这种情况下,如果您使用二进制浮点(这是常见的),那么log(4)将始终正好是log(2)的两倍。由于这不会发生在您身上,因此您使用的log实现似乎无法提供正确的舍入结果。

但是,对于此问题,您还需要log(8)正好是log(2)的三倍,依此类推以获得更多权限。即使log实现确实返回了正确的舍入结果,对于您需要的所有值也不一定如此。对于某些y = x 5 log(y)可能不是log(x)的五倍,因为将log(y)舍入到最接近的可表示值可能会向下舍入而舍入log(x )向上舍入,只是因为精确值恰好位于相对于最近的可表示值的位置。

因此,您甚至不能依赖最佳log实施来确切地告诉您x分数y的确切权限。{{1}}。您可以靠近,然后您可以通过使用整数运算确认或拒绝它来测试结果。可能还有其他方法取决于您的具体情况。

答案 1 :(得分:0)

我想你想要:

/* find the largest x where p^x < n, p is prime, n and x is natural numbers.
 */

define variable p as integer no-undo format ">,>>>,>>>,>>9".
define variable x as integer no-undo format ">>9".
define variable n as integer no-undo format ">,>>>,>>>,>>9".

define variable i as integer no-undo format "->>9".

define variable z as decimal no-undo format ">>9.9999999999".

update p n with side-labels.

/* approximate x
 */

z = log( n ) / log( p ).
display z.

x = integer( truncate( z, 0 )).  /* estimate x                */

/* is p^x < n ?
 */

if exp( p, x ) >= n then
  do while exp( p, x ) >= n:    /* was the estimate too high? */
    assign
      i = i - 1
      x = x - 1
    .
  end.
 else
  do while exp( p, x + 1 ) < n:  /* was the estimate too low? */
    assign
      i = i + 1
      x = x + 1
    .
  end.

display
  x skip
  exp( p, x ) label "p^x" format ">,>>>,>>>,>>9" skip
  i skip
  log( n ) skip
  log( p ) skip
  z skip
 with
  side-labels
.

答案 2 :(得分:0)

问题的根源在于易受浮点截断错误影响的日志函数用于解决自然数域中的问题。首先,我应该指出,实际上,在给出的例子中,1确实是正确的答案。我们正在寻找最大的x,使得p ^ x <1。 N;不是p ^ x&lt; = n。 2 ^ 1&lt; 4,但2 ^ 2不是。也就是说,我们仍然有一个问题,因为当某个x的p ^ x = n时,log(n)除以log(p)可能只是稍微高于整数而不是低于,除非有一些系统性的偏向于执行日志功能。所以在这种情况下,有一些x,其中p ^ x = n,我们实际上希望确保向下舍入到x的下一个较低的整数值。

所以即使像这样的解决方案也无法解决这个问题:

display  truncate(round(log(4) / log(2), 10) , 0) .

我认为有两种方法可以解决这个问题。一个类似于你已经尝试过的,除了因为我们实际上想要向下舍入到下一个较低的自然数,我们会减去而不是添加:

display  truncate(log(4) / log(2)  - 0.00000001, 0) .

只要n小于10 ^ 16,这将起作用,但更整洁的解决方案是用实际整数数学来解决边界条件。当然,如果你得到的数字高于最大整数值,这也会失败。但如果这不是一个问题,你可以使用你的第一个解决方案获得近似解决方案:

display  truncate(log(4) / log(2) , 0) .

然后测试结果是否在等式p ^ x&lt; ñ。如果不小于n,则减1并再试一次。

顺便说一下,顺便说一下,自然数的定义不包括零,所以如果x的最低可能值是1,那么p ^ x的最低可能值是p,所以如果n少于p等于或等于p,没有自然数解。

答案 3 :(得分:0)

大多数计算器也无法计算sqrt {2} * sqrt {2}。问题是我们通常没有那么多的小数。

解决方法:避免TRUNCATE使用ROUND,如

 ROUND(log(4) / log(2), 0).

回合(a,b)将小数a向上舍入到具有b小数的最接近数字。