信用程序不编译
Credit program doesn't compile
我试图编写一个检查银行卡是否有效的 C 程序。
根据 Luhn 的算法,您可以确定信用卡号是否(语法上)有效,如下所示:
从数字的倒数第二位开始,每隔一个数字乘以 2,然后将这些产品的数字相加。
将总和加到未乘以 2 的数字的总和上。
如果总数的最后一位是0(或者,更正式地说,如果总数模10等于0),这个数字是有效的!
这有点令人困惑,所以让我们用我的 AmEx 举个例子:378282246310005。
为了便于讨论,让我们首先在每个数字下划线,从数字的倒数第二个数字开始:
378282246310005
好的,让我们将每个带下划线的数字乘以 2:
7•2 + 2•2 + 2•2 + 4•2 + 3•2 + 0•2 + 0•2
这给了我们:
14 + 4 + 4 + 8 + 6 + 0 + 0
现在让我们将这些产品的数字(即,不是产品本身)加在一起:
1 + 4 + 4 + 4 + 8 + 6 + 0 + 0 = 27
现在让我们将和 (27) 加到未乘以 2 的数字的总和中:
27 + 3 + 8 + 8 + 2 + 6 + 1 + 0 + 5 = 60
是的,总和 (60) 的最后一位数字是 0,所以我的卡是合法的!
因此,验证信用卡号并不难,但手动验证确实有点乏味
#include <cs50.h>
#include <math.h>
#include <stdio.h>
int length(long long n);
int num_at(int x,long long y);
long long flip(double a);
int main(void)
{
//int total2=0;
//printf("Number: ");
//int i=get_int();
long long ll=get_long_long();
//if (ll<=0)
//{
// printf("INVALID\n");
//}
//for (int i=1;2*i<length(ll);i++)
//{
// total2=total2+2*num_at(i,ll);
//}
//int total1=0;
//for (int i=0;2*i<length(ll);i++)
//{
// total1=total1+num_at(i,ll);
//}
//int total=total1+total2;
//printf("%i\n",total);
printf("%lli\n",flip(ll));
}
int length(long long n)/* length of number */
{
long long x=1;
int len=0;
while(n-n%x!=0)/* x % y means x mod y*/
{
len++;
x=x*10;
}
return len;
}
int num_at(int x,long long y)/* digit at specific spot in number */
{
int digit=0;//the digit at position z(see below)
int z=1;
for(z=x;z>=0;z--)
{
digit=y%10;
y=y-y%10;
y=y/10;
}
return digit;
}
long long flip(double a)//flips a
{
long long b=0;
for(int y=0;y<length(a);y++)
{
b=b*10;
b=b+(a%pow(10.0,y+1)-a%pow(10.0,y))/pow(10.0,y);
}
return b;
}
编译时的错误是:
credit.c:99:15: error: invalid operands to binary expression ('double' and 'double')
b=b+(a%pow(10.0,y+1)-a%pow(10.0,y))/pow(10.0,y);
~^~~~~~~~~~~~~~
credit.c:99:31: error: invalid operands to binary expression ('double' and 'double')
b=b+(a%pow(10.0,y+1)-a%pow(10.0,y))/pow(10.0,y);
~^~~~~~~~~~~~
您希望如何在两个双精度值之间进行模运算 (%
)?
10.3 % 5.2
到底是什么?
错误消息只是说,"You cannot do double-modulo-double"
您不能对双精度数(或浮点数)执行取模运算。
这是出于简单的原因,即仅为整数算术定义余数。如果我将 2.3 除以 0.4,余数是多少?
因此,要执行您想要的操作,您需要将 double(a 和 pow 的结果)转换为 long long。
所以你可以 ((long long) a) % (long long) pow( ... )
应该没问题。
以后您应该查看错误消息(以及警告)。
这里明确指出了二进制表达式的无效操作数,并标记了 % 运算符。
pow
returns double 和 %
运算符仅为整数定义。我认为这应该可以解决您的问题。
算法应该比你写的更简单。
我不是 C 程序员,但是:
// transform LL to char []
int len = length(ll);
char card[len];
sprintf(card, "%lld", ll);
int sum =0;
for(i=0;i < len; i++)
{
int num = card[i] - '0';
if(i % 2 == 0)
{ sum += num; }
else
{
int tmp = num * 2;
sum += (tmp / 10);
sum += (tmp % 10);
}
}
if(sum % 10)
{
// card valid
}
在我看来更具可读性。
(对不起,如果打错了,这个 post 是用旧智能手机写的...)
编辑
我知道你喜欢使用循环,但你的 num_at 也可以得到增强:
int num_at(int pos, long long x)
{
return (x / (int)pow(10, pos)) % 10;
}
我试图编写一个检查银行卡是否有效的 C 程序。
根据 Luhn 的算法,您可以确定信用卡号是否(语法上)有效,如下所示:
从数字的倒数第二位开始,每隔一个数字乘以 2,然后将这些产品的数字相加。
将总和加到未乘以 2 的数字的总和上。
如果总数的最后一位是0(或者,更正式地说,如果总数模10等于0),这个数字是有效的!
这有点令人困惑,所以让我们用我的 AmEx 举个例子:378282246310005。
为了便于讨论,让我们首先在每个数字下划线,从数字的倒数第二个数字开始:
378282246310005
好的,让我们将每个带下划线的数字乘以 2:
7•2 + 2•2 + 2•2 + 4•2 + 3•2 + 0•2 + 0•2
这给了我们:
14 + 4 + 4 + 8 + 6 + 0 + 0
现在让我们将这些产品的数字(即,不是产品本身)加在一起:
1 + 4 + 4 + 4 + 8 + 6 + 0 + 0 = 27
现在让我们将和 (27) 加到未乘以 2 的数字的总和中:
27 + 3 + 8 + 8 + 2 + 6 + 1 + 0 + 5 = 60
是的,总和 (60) 的最后一位数字是 0,所以我的卡是合法的!
因此,验证信用卡号并不难,但手动验证确实有点乏味
#include <cs50.h>
#include <math.h>
#include <stdio.h>
int length(long long n);
int num_at(int x,long long y);
long long flip(double a);
int main(void)
{
//int total2=0;
//printf("Number: ");
//int i=get_int();
long long ll=get_long_long();
//if (ll<=0)
//{
// printf("INVALID\n");
//}
//for (int i=1;2*i<length(ll);i++)
//{
// total2=total2+2*num_at(i,ll);
//}
//int total1=0;
//for (int i=0;2*i<length(ll);i++)
//{
// total1=total1+num_at(i,ll);
//}
//int total=total1+total2;
//printf("%i\n",total);
printf("%lli\n",flip(ll));
}
int length(long long n)/* length of number */
{
long long x=1;
int len=0;
while(n-n%x!=0)/* x % y means x mod y*/
{
len++;
x=x*10;
}
return len;
}
int num_at(int x,long long y)/* digit at specific spot in number */
{
int digit=0;//the digit at position z(see below)
int z=1;
for(z=x;z>=0;z--)
{
digit=y%10;
y=y-y%10;
y=y/10;
}
return digit;
}
long long flip(double a)//flips a
{
long long b=0;
for(int y=0;y<length(a);y++)
{
b=b*10;
b=b+(a%pow(10.0,y+1)-a%pow(10.0,y))/pow(10.0,y);
}
return b;
}
编译时的错误是:
credit.c:99:15: error: invalid operands to binary expression ('double' and 'double')
b=b+(a%pow(10.0,y+1)-a%pow(10.0,y))/pow(10.0,y);
~^~~~~~~~~~~~~~
credit.c:99:31: error: invalid operands to binary expression ('double' and 'double')
b=b+(a%pow(10.0,y+1)-a%pow(10.0,y))/pow(10.0,y);
~^~~~~~~~~~~~
您希望如何在两个双精度值之间进行模运算 (%
)?
10.3 % 5.2
到底是什么?
错误消息只是说,"You cannot do double-modulo-double"
您不能对双精度数(或浮点数)执行取模运算。 这是出于简单的原因,即仅为整数算术定义余数。如果我将 2.3 除以 0.4,余数是多少?
因此,要执行您想要的操作,您需要将 double(a 和 pow 的结果)转换为 long long。
所以你可以 ((long long) a) % (long long) pow( ... )
应该没问题。
以后您应该查看错误消息(以及警告)。
这里明确指出了二进制表达式的无效操作数,并标记了 % 运算符。
pow
returns double 和 %
运算符仅为整数定义。我认为这应该可以解决您的问题。
算法应该比你写的更简单。 我不是 C 程序员,但是:
// transform LL to char []
int len = length(ll);
char card[len];
sprintf(card, "%lld", ll);
int sum =0;
for(i=0;i < len; i++)
{
int num = card[i] - '0';
if(i % 2 == 0)
{ sum += num; }
else
{
int tmp = num * 2;
sum += (tmp / 10);
sum += (tmp % 10);
}
}
if(sum % 10)
{
// card valid
}
在我看来更具可读性。 (对不起,如果打错了,这个 post 是用旧智能手机写的...)
编辑 我知道你喜欢使用循环,但你的 num_at 也可以得到增强:
int num_at(int pos, long long x)
{
return (x / (int)pow(10, pos)) % 10;
}