0

我的代码有一点问题,看看信用卡号是否符合 Luhn 算法。当信用卡可被 10 整除时,代码返回 true,但当 CC 编号不能被 10 整除时,代码也返回 true。我已打印出最终总和以确保这些数字实际添加到 sum 变量中,并且他们似乎是.. 下面是我的代码。我知道它可以更干净,但在这个阶段,我希望先看到它工作。

def check_card

   c_num= []

   sum=0

   s_numbers=@card_numbers.to_s.reverse.split("")

   s_numbers.each_slice(2) do |x| 
   c_num << (x.last.to_s.to_i*2)
   c_num << (x.first.to_s.to_i)
     end

  c_num.each do |num|
    if num.to_i > 9
      sum+= (num.to_i % 10)+1
    else 
      sum += num.to_i
    end
  end

sum % 10==0 

end

以下是它的调用方式:

it 'returns false for a bad card' do
  card = CreditCard.new(4408041234567892)
  card.check_card.should eq false
end
4

4 回答 4

1

现在出现了另一个答案,我将提供建议的编码。这不能回答您的问题,但我认为它可能很有趣,并且由于格式限制而不能很好地将其放在评论中。

def valid?(card)
  return false unless card  =~ /^\d+$/ # Ensure card contains only digits
  arr = card.split('').reverse.each_with_index.map {|d, index| (index.odd? ? 2*(d.to_i) : d.to_i)}
  (arr.join.split('').inject(0) {|tot, d| tot + d.to_i}) % 10 == 0
end 

valid?("1234567890123456") => false
于 2013-09-25T21:35:35.603 回答
0

您似乎将测试的输出与check_card方法的输出混淆了。您已经确认sum == 69, 所以sum % 10 == 0应该返回false(除非 Ruby 的数学被破坏),所以您的check_card方法也应该返回false- 在测试块中的行puts card.check_card之后card = CreditCard.new(4408041234567892)(但在下一行之前)添加行以显示返回的值。

下一行 ,card.check_card.should eq false断言返回的值“应该等于” false——也就是说,它期望check_cardfalse的那个值,如果是这种情况@card_numbers,它将返回。true我怀疑您看到测试出现true并认为该方法返回的true.

在没有看到测试输出的情况下,这当然只是猜测。但是,您的代码似乎是正确的,对我来说,给出了正确的结果。

于 2013-09-26T14:07:42.803 回答
0

这是您的代码,经过注释并调整为类似于wikipedia description的行为。

def check_card(str) #creditcardnumber as argument

   c_num = []

   sum = 0

   s_numbers = str.split("") #no reversing. str.split("").map(&:to_i) would save a lot of to_i's later on...
   checksum = s_numbers.pop.to_i #chop off last digit, store as checksum

   s_numbers.each_slice(2) do |x| 
     c_num << (x.last.to_s.to_i*2)
     c_num << (x.first.to_s.to_i)
   end

  c_num.each do |num|
    if num.to_i > 9
      sum+= (num.to_i % 10)+1
    else 
      sum += num.to_i
    end
  end

  (sum * 9) % 10 == checksum 

end

p check_card("79927398713") #=> true
于 2013-09-25T20:25:21.447 回答
0

发布我的答案,因为我认为它很干净:

def valid?(card_number)
  return false unless card_number !~ /\D/

  card_numbers = card_number.reverse.split("").map(&:to_i)
  sum = 0
  card_numbers.each_with_index do |num, i|
    if i.even?
      sum += num
    else
      sum += (num *= 2) > 9 ? num.divmod(10).inject(:+) : num
    end
  end
  sum % 10 == 0
end
于 2016-06-27T04:16:34.787 回答