代码之家  ›  专栏  ›  技术社区  ›  Oglop

Ruby错误:nil不能强制为整数

  •  -1
  • Oglop  · 技术社区  · 3 年前

    我只是在玩一些纯Ruby来获得更好的理解,并试图找到一个数字的素数,而不只是使用素数宝石,我知道,但我写这一切是为了理解,而不是为了解决问题本身。

    我编写了以下代码:

    class LargestPrimeFactor
      # goal: find largest prime factor of 10 to start
    
      attr_accessor :factors_list, :prime_factors, :idx, :below_n, :half_num
    
      def initialize(below_n)
        @below_n        = below_n
        @half_num       = (below_n/2).floor
        @idx            = 2
        @factors_list   = []
        @prime_factors  = []
      end
    
      def prime_checker
        sorted_list         = factors_list.sort
        sorted_list_length  = sorted_list.length
    
        puts "Sorted list of factors so far: #{sorted_list}"
    
        sorted_list.combination(2) do |el, others|
          if !prime_factors.include?(el) && others % el == 0
            prime_factors << el
          end
        end
        puts "Prime checker returned: #{prime_factors}"
      end
    
      def factors
        congruent            = (below_n % idx == 0)
        not_listed           = !factors_list.include?(idx)
        number_candidate     = idx
        factors_list_length  = factors_list.length
    
        if congruent && not_listed && number_candidate
          factors_list << number_candidate
          puts "#{idx}"
          puts "#{below_n}"
          puts "why nil? #{below_n.divmod(idx)[0]}"
          tmp = below_n.divmod(idx)[0] 
          idx = tmp #return number of times it divides in
          puts "idx now: #{idx}"
        elsif factors_list_length > 0 && factors_list[-1] - idx < 0
          primes = prime_checker
          puts "Prime factors: #{primes}"
          puts "COMPLETE"
        else
          idx += 1
        end
      end
    
      def find_primes
        (1..half_num).each do |el|
          factors
        end
      end
    end
     
    p = LargestPrimeFactor.new(below_n=10)
    p.find_primes
    

    但是当我跑的时候 ruby largest_prime_factor.rb 我得到以下输出错误:

    2
    10
    why nil? 5
    idx now: 5
    Traceback (most recent call last):
        5: from largest_prime_factor.rb:65:in `<main>'
        4: from largest_prime_factor.rb:56:in `find_primes'
        3: from largest_prime_factor.rb:56:in `each'
        2: from largest_prime_factor.rb:57:in `block in find_primes'
        1: from largest_prime_factor.rb:46:in `factors'
    largest_prime_factor.rb:46:in `-': nil can't be coerced into Integer (TypeError)
    

    我很困惑,因为我认为 idx 将被设置为 5 在第46行,但我把它解释为 nil 以某种方式关于如何在这个方法中访问和设置这个变量,我遗漏了什么?

    谢谢

    1 回复  |  直到 3 年前
        1
  •  2
  •   mechnicov    3 年前

    西尔维奥·马约洛没有解释错误

    更改实例变量的问题只是问题之一。但原因是另一个

    例如,此代码:

    class Foo
      attr_accessor :bar
    
      def initialize
        @bar = 0
      end
    
      def baz
        p x
    
        10.times do
          if bar < 6
            @bar += 1
          end
        end
      end
    end
    
    Foo.new.baz
    

    将提高

    undefined local variable or method `x'
    

    但是这个代码:

    class Foo
      attr_accessor :bar
    
      def initialize
        @bar = 0
      end
    
      def baz
        10.times do
          if bar < 6
            x = 1
            @bar += 1
          else
            p x
          end
        end
      end
    end
    
    Foo.new.baz
    

    将打印

    nil
    nil
    nil
    nil
    

    所以 factors_list[-1] - idx < 0 在你的代码中会出现错误。局部变量 idx 已声明,但未初始化,因为 if 分支未被执行

    我很惊讶为什么你的问题被否决了。读者和西尔维奥·马约洛都还没有弄明白这个问题

        2
  •  2
  •   Silvio Mayolo    3 年前

    你宣称自己是读者,但不是作家 @idx ,所以 idx 工作并返回实例变量 @idx ,你不能给它写信。

    或者直接写入实例变量( @idx = 5 ),或者成为一名作家( attr_accessor :idx )写信给 self.idx ( self.idx = 5 ).注意,在后一种情况下 self 是必需的,这样您就不会意外地使用相同的名称创建新的局部变量。

    你的 idx += 1 行也需要进行类似的更新,以及尝试写入访问器的任何其他位置。