【问题标题】:Luhn Algorithm in RubyRuby 中的 Luhn 算法
【发布时间】:2013-08-10 22:13:54
【问题描述】:

我一直在尝试在 Ruby 中实现 Luhn 算法,但不断收到错误消息,即无法将 nil 转换为 Fixnum。

Luhn 算法应该:

从倒数第二个数字开始,每隔一个数字加倍,直到到达第一个数字

将所有未触及的数字和两位数相加(两位数需要分开,10变成1 + 0)

如果总数是 10 的倍数,则您已收到有效的信用卡号!

这就是我所拥有的:

class CreditCard
  def initialize (card_number)
    if (card_number.to_s.length != 16 )
        raise ArgumentError.new("Please enter a card number with exactly 16 integars")
    end
    @card_number = card_number
    @total_sum = 0
  end

  def check_card
    @new_Array = []
    @new_Array = @card_number.to_s.split('')
    @new_Array.map! { |x| x.to_i }
    @new_Array.each_with_index.map { |x,y| 
      if (y % 2 != 0) 
        x = x*2
      end  
     }  
    @new_Array.map! {|x| 
     if (x > 9)
        x = x-9 
      end  
    }
    @new_Array.each { |x| 
        @total_sum = @total_sum + x
    }  
    if (@total_sum % 10 == 0)
      return true
    else
      return false      
    end  
  end  
end

【问题讨论】:

    标签: ruby algorithm luhn


    【解决方案1】:
    if (x > 9)
      x = x-9
    end
    

    =>

    x > 9 ? x - 9 : x
    

    或者你也可以写

    if x > 9
      x - 9
    else
      x
    end
    

    如果没有else 子句,if false; ...; end 的值将始终为nil

    【讨论】:

      【解决方案2】:

      在你的部分

      @new_Array.each_with_index.map { |x,y| 
        if (y % 2 != 0) 
          x = x*2
        end  
      }
      

      更改不是永久性的。此外,正如 Victor 所写,如果测试失败,您的 @new_Array 将被 nil 填充。最后

      if (@total_sum % 10 == 0)
        return true
      else
        return false      
      end
      

      你可以简单地写

      @total_sum % 10 == 0
      

      因为 ruby​​ 方法的最后一行已经是一个返回值。我找到了slightly different algorithm 并在这里实现了它:

      # 1) Reverse the order of the digits in the number.
      # 2) Take the first, third, ... and every other odd digit in the reversed digits
      #   and sum them to form the partial sum s1
      # 3) Taking the second, fourth ... and every other even digit in the reversed digits:
      #   a) Multiply each digit by two (and sum the digits if the answer is greater than nine) to form partial sums for the even digits
      #   b) Sum the partial sums of the even digits to form s2
      # 4) If s1 + s2 ends in zero then the original number is in the form of a valid credit card number as verified by the Luhn test.
      
      def luhn n
        s = n.to_s.reverse
        sum=0
        tmp=0
        (0..s.size-1).step(2) {|k|    #k is odd, k+1 is even
          sum+=s[k].to_i   #s1
          tmp = s[k+1].to_i*2
          tmp = tmp.to_s.split(//).map(&:to_i).reduce(:+) if tmp>9
          sum+=tmp
        }
        sum%10 == 0
      end
      
      [49927398716, 49927398717, 1234567812345678, 1234567812345670].each {|num|
        puts "%20s %s" % [num, luhn(num)]
      }
      
      #         49927398716 true
      #         49927398717 false
      #    1234567812345678 false
      #    1234567812345670 true
      

      希望这会有所帮助。

      【讨论】:

        【解决方案3】:

        如果您不介意更改代码...

        ...
        def check_card
          sum = 0
          @card_number.to_s.split("").each_with_index do |digit, index|
            d = digit.to_i
            sum += index % 2 == 1 ? d : d * 2 > 9 ? ( d * 2 - 9) : d * 2 
          end
          sum % 10 == 0
        end
        

        这只是立即得到数字的总和,如果索引是偶数(从数组索引的角度来看,从第二个到最后一个开始的每隔一个数字是偶数)将它加倍并减去 9。然后最后做模10吗

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-30
          • 2015-03-11
          • 1970-01-01
          • 1970-01-01
          • 2015-01-01
          • 2021-05-16
          • 2023-04-05
          • 1970-01-01
          相关资源
          最近更新 更多