【问题标题】:Bignum too big to convert into 'long' (RangeError)Bignum 太大而无法转换为“长”(RangeError)
【发布时间】:2015-11-27 04:04:55
【问题描述】:

尝试自学 ruby​​ - 我正在研究 ruby​​ 中的 Project Euler 问题 14。

n = 1000000
array = Array.new(n,0)
#array[x] will store the number of steps to get to one if a solution has been found and 0 otherwise. x will equal the starting number. array[0] will be nonsensical for these purposes
i = n-1#We will start at array[n-1] and work down to 1
while i > 1
    if array[i] == 0
        numstep = 0 #numstep will hold the number of loops that j makes until it gets to 1 or a number that has already been solved
        j = i
        while j > 1 && (array[j] == 0 || array[j] == nil)
            case j%2
            when 1 # j is odd
                j = 3*j + 1
            when 0 # j is even
                j = j/2
            end
            numstep += 1
        end
        stop = array[j] #if j has been solved, array[j] is the number of steps to j = 1. If j = 1, array[j] = 0
        j = i
        counter = 0
        while j > 1 && (array[j] == 0 || array[j] == nil)
            if j < n
                array[j] = numstep + stop - counter #numstep + stop should equal the solution to the ith number, to get the jth number we subtract counter
            end

            case j%2
            when 1 #j is odd
                j = 3*j+1
            when 0 #j is even
                j = j/2
            end
            counter += 1
        end
    end
    i = i-1
end

puts("The longest Collatz sequence starting below #{n} starts at #{array.each_with_index.max[1]} and is #{array.max} numbers long")

此代码适用于 n = 100000 及以下,但当我上升到 n = 1000000 时,它会运行一段时间(直到 j = 999167 *3 + 1 = 2997502)。当它尝试访问数组的第 2997502 个索引时,它会抛出错误

in '[]': bignum too big to convert into 'long' (RangeError) 

在第 27 行(这是 while 语句:

while j > 1 && (array[j] == 0 || array[j] == nil)

我怎样才能让它不引发错误?检查数组是否为零可以节省代码效率,因为它允许您不重新计算已经完成的事情,但是如果我删除 and 语句,它会运行并给出正确的答案。我很确定问题在于数组的索引不能是大数字,但也许有一种方法可以声明我的数组,这样它就可以了?我不太关心答案本身。我实际上已经在 C# 中解决了这个问题 - 只是想学习 ruby​​,所以我想知道我的代码为什么会这样做(如果我错了)以及如何解决它。

【问题讨论】:

  • 2997502 不是太大,无法转换为 long,它甚至不是一个特别大的数组。不知何故,您正在创建一个更大的数字。
  • 您的程序对我来说运行良好,并打印出正确的结果。您使用的是哪个版本的 ruby​​?

标签: ruby bignum


【解决方案1】:

对于在可接受的时间内产生输出的任何输入,上面的代码对我来说运行愉快。我相信这是因为您可能会在 32 位架构或类似的架构上遇到问题。无论如何,所述问题的解决方案很简单(除非您可能会耗尽内存,这是另一个可能的故障。)

数组索引是有限的,从你得到的错误如下。太棒了,让我们改用哈希!

n = 1000000
array = Hash.new(0)
#array[x] will store the number of steps to get to one if a solution has been found and 0 otherwise. x will equal the starting number. arr
i = n-1#We will start at array[n-1] and work down to 1
while i > 1 
  if array[i].zero?
        numstep = 0 #numstep will hold the number of loops that j makes until it gets to 1 or a number that has already been solved
        j = i 
        while j > 1 && array[j].zero?
            case j%2 
            when 1 # j is odd
                j = 3*j + 1 
            when 0 # j is even
                j = j/2 
            end
            numstep += 1
        end
        stop = array[j] #if j has been solved, array[j] is the number of steps to j = 1. If j = 1, array[j] = 0
        j = i 
        counter = 0 
        while j > 1 && array[j].zero?
            if j < n 
                array[j] = numstep + stop - counter #numstep + stop should equal the solution to the ith number, to get the jth number we 
            end

            case j%2 
            when 1 #j is odd
                j = 3*j+1
            when 0 #j is even
                j = j/2 
            end
            counter += 1
        end
    end 
    i = i-1 
end


puts("Longest Collatz below #{n} @#{array.sort_by(&:first).map(&:last).each_with_index.max[1]} is #{arr

请注意,由于我使用带有初始化程序的哈希,array[i] 不能成为 nil,这就是为什么只检查零值的原因。

【讨论】:

  • 谢谢,我不知道哈希。使用它对我来说很好。请注意,您的 puts 语句运行不正确 - 它返回的是第二高的数字,而不是最高的,但我不知道为什么。做了一些关于哈希的阅读并将其替换为: puts("#{n} 以下的最长 Collat​​z 序列是 #{array.max_by{|k,v| v}[1]} 数字长,从 #{array.max_by {|k,v| v}[0]}.")
  • 我没有太注意输出,我只是想展示一个解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-07
  • 1970-01-01
  • 2021-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多