CS50-Week1-More

文章发布时间:

最后更新时间:

文章总字数:
1.2k

预计阅读时间:
5 分钟

Problem Set

Credite

看不懂。。。

Luhn’s Algorithm
So what’s the secret formula? Well, most cards use an algorithm invented by Hans Peter Luhn of IBM. According to Luhn’s algorithm, you can determine if a credit card number is (syntactically) valid as follows:

  1. Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together.
  2. Add the sum to the sum of the digits that weren’t multiplied by 2.
  3. If the total’s last digit is 0 (or, put more formally, if the total modulo 10 is congruent to 0(与 0 一致)), the number is valid!

That’s kind of confusing, so let’s try an example with David’s Visa: 4003600000000014.

For the sake of discussion(为了讨论的缘故), let’s first underline every other digit, starting with the number’s second-to-last(倒数第二) digit:

4 0 6 0 0 0 0 1

Okay, let’s multiply(乘) each of the underlined digits by 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

Now let’s add those products’ digits (i.e., not the products themselves) together:(仅看数字,不看乘法结果)

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 (加上没有被 2 乘的数,即倒数第一个数开始)(starting from the end):

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

Yup, the last digit in that sum (20) is a 0, so David’s card is legit!

So, validating credit card numbers isn’t hard, but it does get a bit tedious by hand. Let’s write a program.

现在懂了,感谢划词翻译,检测 credit 类型,并换行output be AMEX\n or MASTERCARD\n or VISA\n or INVALID\n

注意 oj 细节,另外,get_long()可以拒绝非法字符和字长并循环执行直到输入合法,我们只需要拒绝不符合 credit 长度的数值即可

思路:计算数字位数,不断将其除以 10,直到其商为 0,执行次数即为数字的位数

1
2
3
4
5
6
7
8
9
10
11
12
int bit = 0;
long temp = credit;
while (temp != 0)
{
temp = temp / 10;
bit++;
}
if ((bit != 13)&&(bit != 15)&&(bit !=16))
{
printf("INVALID\n");
return 1;
}

如果 bit 既不等于 13,15 也不等于 16,程序在此次结束

对于合法数字,进行下一步,获得其隔位数值

对于 128,有$128 = 1100+210+8*1$

可得其每位数值为 1,2,8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int i = 1 * pow(10,i - 1);//math.h库 幂函数
temp = credit
while (temp != 0)
{
temp = temp / bit; //取首位数值 待优化
}

//另一种方案 待优化
for (int i = 2;i < bit;i += 2)
{
int power = 1 * pow(10,i - 1);
temp = temp / power;
printf("%ld\n",temp);
}

最后问了 ddb

怎么获取数字的每一位的数值啊

ddb
在计算机科学中,我们可以通过取模运算符(%)和整除运算符(/)来获取一个数字的每一位。例如,如果你有一个数字 12345,你可以通过 12345 % 10 来获取最后一位,也就是 5。然后,你可以通过 12345 / 10 来去掉最后一位,得到 1234。然后你可以重复这个过程,直到数字变为 0。这个方法在任何编程语言中都可以实现,你可以试试看。

我是菜鸟

ddb 方案,因为每次都处理末尾的个位,所以不涉及 10,1000,1000 等次方变化。

1
2
3
4
5
6
7
temp = credit;
while (temp != 0)
{
int final = temp % 10;
temp = temp / 10;
printf("%i\n%ld\n",final,temp);
}

于是我们每次的相当于取十位的数值,将 10 改为 100,每次可同时获得十位与个位的值,再除以 10,去掉个位,即所需的值,下文中取倒数第一及间隔值同理,并进行合法性判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
temp = credit;
int second = 0;
while (temp != 0)
{
int final = temp % 100;
temp = temp / 100;
final = final / 10;

if (final * 2 >= 10)
{
second += final / 10 + final % 10;
}
else
{
second += final * 2;
}
}
temp = credit;
int last = 0;
while (temp != 0)
{
int final = temp % 100;
temp = temp / 100;
final = final % 10;


last += final;
}
if ((second + last) % 10 != 0)
{
printf("INVALID");
}

写到这因为英语四级考试耽搁两三天,再看已经看不懂了
然后用瞪眼法printf()检查程序时发现了难蚌之处

1
2
3
4
5
6
7
while (temp != 0)
{
int final = temp % 100;
temp = temp / 100;
final = final % 10;
last += final;
}

太睿智了我,final 赋值位置在求和语句位置写到下面去了
调整两次计算 final 的语句位置,输出正常

最后是卡类判断,不难,就不写了,就是写了一堆冗余代码[/233]
使用了 math 库的两个函数

一个浮点数怎么取整
ddb
在 C 语言中,你可以使用几种不同的方法来取整一个浮点数。例如,你可以使用 floor()函数来向下取整,或者使用 ceil()函数来向上取整。如果你想要四舍五入,你可以使用 round()函数。这些函数都在 math.h 库中,所以你需要在你的代码中包含这个库。

评测,过啦,真不容易

源代码

【已编辑】

并不难,就不放出来了。