简体   繁体   English

如何在 C 中添加产品数字而不是产品本身?

[英]How to add product digits rather than products themselves in C?

I am trying to finish an assignment in C for the CS50 course in which I must implement Luhn's algorithm to validate a credit card number.我正在尝试为 CS50 课程完成 C 中的作业,在该课程中我必须实施 Luhn 的算法来验证信用卡号。 Here is a quick example to elaborate:这是一个详细说明的快速示例:


credit card number: 4003600000000014.信用卡号码:4003600000000014。
Now for every other digit, starting with the number's second-to-last digit:现在对于每个其他数字,从数字的倒数第二个数字开始:

1-0-0-0-0-6-0-4 1-0-0-0-0-6-0-4

Let's multiply each of the digits by 2:让我们将每个数字乘以 2:

1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2 1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2

That gives us:这给了我们:

2 + 0 + 0 + 0 + 0 + 12 + 0 + 8 2 + 0 + 0 + 0 + 0 + 12 + 0 + 8

Now let's add those products' digits (ie, not the products themselves) together:现在让我们将这些产品的数字(即,不是产品本身)加在一起:

2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13 2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13

Now let's add that sum (13) to the sum of the digits that weren't multiplied by 2 (starting from the end):现在让我们将总和 (13) 添加到未乘以 2 的数字的总和(从末尾开始):

13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20 13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20

Yup, the last digit in that sum (20) is a 0, so the number is valid.是的,总和 (20) 中的最后一个数字是 0,所以这个数字是有效的。


I figured out how to extract each number in the credit card individually (I know my way is boring and probably not practical), so the next step is to multiply every other number by two and add (the products' digits, not the digits themselves) and this is what I need help of how to do it?我想出了如何单独提取信用卡中的每个数字(我知道我的方法很无聊而且可能不实用),所以下一步是将每个其他数字乘以 2 并添加(产品的数字,而不是数字本身) 这就是我需要帮助的方法吗? MY code:我的代码:

#include <cs50.h>
#include <stdio.h>
#include <math.h>

int main(void)
{
    long credit_card_number;
    do
    {
        credit_card_number = get_long("Enter your credit card number: ");

    }
    while (credit_card_number < 1 || credit_card_number > 9999999999999999);

    //American Express uses 15-digit numbers. American Express numbers start with 34 or 37
    //MasterCard uses 16-digit numbers. MasterCard numbers start with 51, 52, 53, 54, or 55.
    //Visa uses 13- and 16-digit numbers. Visa numbers start with 4.
    // checksum

    long last_number;
    long credit_card_without_last_number;
    long second_to_last_number;
    long credit_card_without_second_number;
    long third_number;
    long credit_card_without_third_number;
    long fourth_number;
    long credit_card_without_fourth_number;
    long fifth_number;
    long credit_card_without_fifth_number;
    long sixth_number;
    long credit_card_without_sixth_number;
    long seventh_number;
    long credit_card_without_seventh_number;
    long eighth_number;
    long credit_card_without_eighth_number;
    long ninth_number;
    long credit_card_without_ninth_number;
    long tenth_number;
    long credit_card_without_tenth_number;
    long eleventh_number;
    long credit_card_without_eleventh_number;
    long twelfth_number;
    long credit_card_without_twelfth_number;
    long thirteenth_number;
    long credit_card_without_thirteenth_number;
    long fourteenth_number;
    long credit_card_without_fourteenth_number;
    long fifteenth_number;
    long credit_card_without_fifteenth_number;
    long sixteenth_number;

    long multiply_digits;

    //separating each number starting from the last (right)in its own variable.
    last_number = credit_card_number % 10;
    credit_card_without_last_number = credit_card_number / 10;

    second_to_last_number = credit_card_without_last_number % 10;
    credit_card_without_second_number = credit_card_without_last_number / 10;

    third_number = credit_card_without_second_number % 10;
    credit_card_without_third_number = credit_card_without_second_number / 10;

    fourth_number = credit_card_without_third_number % 10;
    credit_card_without_fourth_number = credit_card_without_third_number / 10;

    fifth_number = credit_card_without_fourth_number % 10;
    credit_card_without_fifth_number = credit_card_without_fourth_number / 10;

    sixth_number = credit_card_without_fifth_number % 10;
    credit_card_without_sixth_number = credit_card_without_fifth_number / 10;

    seventh_number = credit_card_without_sixth_number % 10;
    credit_card_without_seventh_number = credit_card_without_sixth_number / 10;

    eighth_number = credit_card_without_seventh_number % 10;
    credit_card_without_eighth_number = credit_card_without_seventh_number / 10;

    ninth_number = credit_card_without_eighth_number % 10;
    credit_card_without_ninth_number = credit_card_without_eighth_number / 10;

    tenth_number = credit_card_without_ninth_number % 10;
    credit_card_without_tenth_number = credit_card_without_ninth_number / 10;

    eleventh_number = credit_card_without_tenth_number % 10;
    credit_card_without_eleventh_number = credit_card_without_tenth_number / 10;

    twelfth_number = credit_card_without_eleventh_number % 10;
    credit_card_without_twelfth_number = credit_card_without_eleventh_number / 10;

    thirteenth_number = credit_card_without_twelfth_number % 10;
    credit_card_without_thirteenth_number = credit_card_without_twelfth_number / 10;

    fourteenth_number = credit_card_without_thirteenth_number % 10;
    credit_card_without_fourteenth_number = credit_card_without_thirteenth_number / 10;

    fifteenth_number = credit_card_without_fourteenth_number % 10;
    credit_card_without_fifteenth_number = credit_card_without_fourteenth_number / 10;

    sixteenth_number = credit_card_without_fifteenth_number % 10;

    //Here I need the help to multiply these numbers by two and then add each product's
    //digits to the rest of the unused numbers.
    multiply_digits = (second_to_last_number*2)+(fourth_number*2)+(sixth_number*2)+(eighth_number*2)+(tenth_number*2)+(twelfth_number*2)+(fourteenth_number*2)+(sixteenth_number*2);

}

Try doing this instead尝试这样做

int main(){
    long cNo = 4003600000000014;
    int arr[16];

    for(int i=0; i<16; i++){
        arr[15-i] = cNo % 10;
        cNo /= 10;
    }

    int multipliedSum = 0;
    for(int i=0; i<16; i++){
        if(i%2==1)
            multipliedSum += arr[i];
        else{
            if(arr[i]*2<10){
                multipliedSum += (arr[i]*2);
            }else{
                int num = arr[i]*2;
                while(num){
                    multipliedSum += num%10;
                    num/=10;
                }
            } 
        }
    }

    printf("valid = %s\n",multipliedSum%10==0?" True": " False");
}

You will get the following你会得到以下

valid = True有效 = 真

A general algorithm for adding digits (assuming an integer type):添加数字的通用算法(假设 integer 类型):

  1. Initialize your sum to 0: sum = 0将总和初始化为 0: sum = 0
  2. Extract the lowest digit from the number using the % modulus operator: digit = number % 10使用%模运算符从数字中提取最低位: digit = number % 10
  3. Add the value of that digit to the sum: sum += digit (shorthand for sum = sum + digit )将该数字的值添加到总和中: sum += digitsum = sum + digit的简写)
  4. Divide the number by 10: number /= 10 (shorthand for number = number / 10将数字除以 10: number /= 10 (数字的简写number = number / 10
  5. If the number is non-zero after dividing by 10, go back to 2如果除以 10 后数非零,go 回到 2
  6. End结尾

The modulus operator % returns the integer remainder of an integer division - 123 / 10 == 12 rem 3 .模运算符%返回 integer 除法的 integer 余数 - 123 / 10 == 12 rem 3 So the remainder of dividing the number by 10 is the least significant decimal digit of the number.因此,将数字除以 10 的余数是该数字的最低有效十进制数字。 Notice that integer division gives you an integer result - 123 / 10 == 12 , not 12.3 .请注意, integer 除法为您提供 integer 结果 - 123 / 10 == 12 ,而不是12.3

You'll want to put this in a separate function, so you can write something like你会想把它放在一个单独的 function 中,所以你可以写类似的东西

int sumdig( int v )
{
  ...
}

int main( void )
{
   int value = 123;
   int sum = sumdig( value ); // sumdig will return 1 + 2 + 3, or 6
   ...
}

When you find yourself creating a bunch of separate variables of the same type with the same name except for some tacked-on ordinal ( var1 , var2 , var3 or first_thing , second_thing , third_thing ), that's a real strong hint you want to use an array .当您发现自己创建了一堆具有相同名称的相同类型的单独变量时,除了一些附加的序数( var1var2var3first_thingsecond_thingthird_thing ),这是您想要使用数组的真正强烈提示. You can use an array to store the individual digits of your card number:您可以使用数组来存储卡号的各个数字:

int number[16];

and use the % 10 method as described above to extract the individual digits:并使用上述% 10方法提取各个数字:

long tmp = credit_card_number; // use a temporary so we preserve the original card number
for ( int i = 0; i < 16; i++ )
{
  number[i] = tmp % 10;
  tmp /= 10;
}

This means that the least significant (rightmost) card number digit will be stored in number[0] and the most significant (leftmost) card number digit will be stored in number[15] , so be aware of that.这意味着最低有效(最右边)的卡号数字将存储在number[0]中,最高有效(最左边)的卡号数字将存储在number[15]中,因此请注意这一点。 For the purposes of validating the number it doesn't matter, but if you want to display the contents of the array you'll have to take that into account.出于验证数字的目的,这并不重要,但如果要显示数组的内容,则必须考虑到这一点。

Using an array makes it easier to extract subsets of digits:使用数组可以更轻松地提取数字子集:

for ( int i = 1; i < 16; i += 2 ) // hit every other element starting at element 1
{
  number[i] *= 2; // multiply these digits by 2
}

That loop above executes the "1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2" portion of your algorithm.上面的循环执行算法的“1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2”部分。

You should be able to figure out the rest from there.您应该能够从那里找出 rest。 Hope this helps.希望这可以帮助。

Hint: to extract one digit from a number, mod it by 10 .提示:要从一个数字中提取一位数字,请将其修改为10 So say that you want to figure out the sum of the digits of a number, say 123456 , you will do the following: (pseudocode)所以说你想找出一个数字的数字之和,比如123456 ,你将执行以下操作:(伪代码)

number=123456;
sum=0;
loop if number is not 0{
sum+=number % 10;
number-=number % 10;
number=(int)(number/10);
}

Now try to implement it as a function, say digit() , and when you are trying to add some numbers digit-wise, say 123 and 456 , just do digit(123)+digit(456) instead.现在尝试将其实现为 function,例如digit() ,当您尝试按数字添加一些数字时,例如123456 ,只需执行digit(123)+digit(456)即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM