大量的立方根

时间:2014-08-29 02:22:33

标签: ruby

我试图识别大量的立方根。我找到了一个解决方案,适用于较小的数字,但不是在这种情况下:

require 'openssl'
q = OpenSSL::BN::generate_prime(2048)
ti = q.to_i        #=> 3202718747...
ti3 = ti ** 3      #=> 328515909...
m = ti3 ** (1/3.0) #=> Infinity

我希望看到m = ti的原始输出。是的,这是Matasano挑战的一部分。到目前为止,我已经花了很多精力去寻求帮助,但是我已经达到了这样一个地步:#我该如何做一些简单的事情,在Ruby&#34 ;。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:1)

在整数的ruby操作中,自动升级为bignums(任意精度整数),因此永远不会出现溢出。

浮点运算也是如此:你最终得到无穷大,因为提升到1/3的幂是一个浮点运算,它做的第一件事是尝试将你的数字转换为浮点运算。红宝石中浮动的最大数字可以代表大约10 ^ 308,而你的数字可能大约是10 ^ 1800大关,所以它拯救并返回无限

Ruby有一个BigDecimal类。因此你可能想要做

BigDecimal.new(ti3) ** (1/3.0)

这给了我一个非常错误的答案 - 我怀疑因为(1 / 3.0)是一个浮点数,所以只有大约1/3

BigDecimal.new(ti3) ** Rational(1,3)

另一方面为我产生正确的结果(误差可以忽略不计)。 Rational是Ruby用于以精确方式表示分数的类。在ruby 2.1中,您可以将其缩短为

BigDecimal.new(ti3) ** (1r/3)

文档确实说只支持整数指数,但这似乎是红宝石1.8天的宿醉

答案 1 :(得分:0)

我不知道Matasano的挑战是什么,但我想到的是Newton's Method

Cube Roots上的维基百科页面也建议使用牛顿法

答案 2 :(得分:0)

根据给出的两条建议提出以下代码。

def nthroot(n, a, precision = 1e-1024)
  x = a
  begin
    prev = x
    x = ((n - 1) * prev + a / (prev ** (n - 1))) / n
  end while (prev - x).abs > precision
 x
 end

它基于牛顿方法的实现,它处理浮点数,但也只是返回无穷大。此版本仅处理整数,但适用于大整数。

当然,可以用n = 3来调用nthroot。