I'm a beginner in CS50 trying to do the Credit problem from Problem Set 1. We are using C. The problem asks us to validate credit card numbers using Luhn's algorithm. I was going to use an array, but code using one wasn't easy to understand for me.
I'm trying to type out the full Luhn formula to calculate. I don't know where I'm messing up. Every time I run a card number that's supposed to be valid, it's never card_total % 10 = 0 like it should be.
Example Card Number: 4003600000000014 => checksum total (int card_total) = 33
Below is just code that asks for the credit card number, runs it through the algorithm, and prints out the total checksum just for me to see if it's working properly. I know this is really long, but this is just for my understanding of all the pieces. I've written much shorter and nicer code before. I swear!
EDIT: I run my code in the cs50 VS virtual codespace, which uses Linux I think. I will take the advice of changing the other ints to longs and see if this fixes my problem. My formulas are consistent, so this is a formatting issue. Once this is fixed, the rest of the problem is easy to solve.
Someone mentioned my complicated calculations. Sorry. I know this could be more brief, but I just wanted to follow the algorithm so I can see what's going on. The lecture for this week didn't touch on going through arrays or manipulating strings, so I'm just doing what I know so far in C. This would be a lot easier in python.
EDIT 2: All that needed to change was int to long. The code now works perfectly and incorporates properly with the rest of my code checking for Amex, Visa, etc. THANK YOU SO MUCH!
#include <cs50.h>
#include <stdio.h>
int get_number(void);
int main(void)
{
long n = get_number();
//calculating card number with modulo
long a = ((n % 10000000000000000) / 1000000000000000);
long b = ((n % 1000000000000000) / 100000000000000);
long c = ((n % 100000000000000) / 10000000000000);
long d = ((n % 10000000000000) / 1000000000000);
long e = ((n % 1000000000000) / 100000000000);
long f = ((n % 100000000000) / 10000000000);
long g = ((n % 10000000000) / 1000000000);
long h = ((n % 1000000000) / 100000000);
long i = ((n % 100000000) / 10000000);
long j = ((n % 10000000) / 1000000);
long k = ((n % 1000000) / 100000);
long l = ((n % 100000) / 10000);
long m = ((n % 10000) / 1000);
long ene = ((n % 1000) / 100);
long o = ((n % 100) / 10);
long p = ((n % 10) / 1); //The "/ 1" is just for visualization
// multiply odd numbers by 2 //Also for visualization
long q = a * 2;
long r = c * 2;
long s = e * 2;
long t = g * 2;
long u = i * 2;
long v = k * 2;
long w = m * 2;
long x = o * 2;
//process odd products //Luhn's has exceptions for double digit numbers
long qq;
if (q < 10)
{
qq = ((q % 10) + ((q % 100)/10));
}
else if (q > 10)
{
qq = (q % 10) + 1;
}
else if (q == 10)
{
qq = 1;
}
else
{
qq = q;
}
long rr;
if (r < 10)
{
rr = ((r % 10) + ((r % 100) / 10));
}
else if (r > 10)
{
rr = (r % 10) + 1;
}
else if (r == 10)
{
rr = 1;
}
else
{
rr = r;
}
long ss;
if (s < 10)
{
ss = ((s % 10) + ((s % 100) / 10));
}
else if (s > 10)
{
ss = (s % 10) + 1;
}
else if (s == 10)
{
ss = 1;
}
else
{
ss = s;
}
long tt;
if (t < 10)
{
tt = ((t % 10) + ((t % 100) / 10));
}
else if (t > 10)
{
tt = (t % 10) + 1;
}
else if (t == 10)
{
tt = 1;
}
else
{
tt = t;
}
long uu;
if (u < 10)
{
uu = ((u % 10) + ((u % 100) / 10));
}
else if (u > 10)
{
uu = (u % 10) + 1;
}
else if (u == 10)
{
uu = 1;
}
else
{
uu = u;
}
long vv;
if (v < 10)
{
vv = ((v % 10) + ((v % 100) / 10));
}
else if (v > 10)
{
vv = (v % 10) + 1;
}
else if (v == 10)
{
vv = 1;
}
else
{
vv = v;
}
long ww;
if (w < 10)
{
ww = ((w % 10) + ((w % 100) / 10));
}
else if (w > 10)
{
ww = (w % 10) + 1;
}
else if (w == 10)
{
ww = 1;
}
else
{
ww = w;
}
long xx;
if (x < 10)
{
xx = ((x % 10) + ((x % 100) / 10));;
}
else if (x > 10)
{
xx = (x % 10) + 1;
}
else if (x == 10)
{
xx = 1;
}
else
{
xx = x;
}
//Sum processed odd products
long total_odd = qq + rr + ss + tt + uu + vv + ww + xx;
//sum total odd products and even card numbers
long bb = ((b % 10) + ((b % 100) / 10));
long dd = ((d % 10) + ((d % 100) / 10));
long ff = ((f % 10) + ((f % 100) / 10));
long hh = ((h % 10) + ((h % 100) / 10));
long jj = ((j % 10) + ((j % 100) / 10));
long ll = ((l % 10) + ((l % 100) / 10));
long eneene = ((ene % 10) + ((ene % 100) / 10));
long pp = ((p %10) + ((p % 100) / 10));
long total_even = bb + dd + ff + hh+ jj + ll + eneene + pp;
//sum odd & even
long card_total = total_odd + total_even;
printf(" %li\n", card_total);
}
int get_number(void) //Works perfectly
{
long n;
do
{
n = get_long("Number: "); // Records credit card number
}
while (n < 1000000000000 || n > 5599999999999999); // CC at least 13 digits but < 17 digits
return n;
}
Trying out your code and debugging it, the issue I found right away is that the return size element for your "get_number" function is too small.
int get_number(void);
When I debugged the returned value to the main function, the value was a negative number since the integer return value is too small for your long integer.
Changing the function definition to "long get_number(void)" in the prototype and the function, allowed for the entered value to flow back to the main function and get tested properly. Following was the test output on my terminal (FYI, I added a couple of printf statements to illustrate that the entered value was flowing through properly).
#Vera:~/C_Programs/Console/CC_Luhn/bin/Release$ ./CC_Luhn
Number: 4003600000000014
Value stored is: 4003600000000014
Returned number: 4003600000000014
20
Just as a double-check, I ran a Luhn calculator program I had built some time back to answer a similar problem. Following is the output again using your credit card example as input.
#Vera:~/C_Programs/Console/Luhn/bin/Release$ ./Luhn
Enter a number: 4003600000000014
Length of number is: 16
Digit is: 4 Value is: 8 Sum is 8
Digit is: 0 Value is: 0 Sum is 8
Digit is: 0 Value is: 0 Sum is 8
Digit is: 3 Value is: 3 Sum is 11
Digit is: 6 Value is: 3 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 1 Value is: 2 Sum is 16
Digit is: 4 Value is: 4 Sum is 20
Valid
The result of the final calculation was the value of "20" which is a number that ends in zero, which indicates a valid number.
This might have been a bit verbose, but the bottom line is be careful mixing your integer sizes in functions and formulas.
Give that a try to see if it meets the spirit of your project.
Related
So, I'm trying to make Luhn's algorithm in C, but it doesn't return the correct values when running it.
//Luhn's Algorithm
int tsum = 0;
if (count % 2 != 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 != 0)
{
tsum += (cardNum % 10);
}
else
{
tsum += (cardNum % 10)*2;
}
cardNum /= 10;
}
}
else
if (count % 2 == 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 == 0)
{
tsum += (cardNum % 10);
}
else
{
tsum += (cardNum % 10)*2;
}
cardNum /= 10;
}
}
tsum %= 10;
I have spent hours trying to troubleshoot and find the issue, count represents the number of digits in the card number, the rest define themselves.
I would appreciate somebody to tell me what I'm doing wrong, thank you.
EDIT: Apologies, cardNum is a long long. And I am expecitng a value of 0 for tsum when inputting any card number from Paypal's Standard Test Cards. I would also like to add, in my mind what this code should do is: using the checks for even and odd it will start from the rightmost digit and add it to tsum, every other digit will do the same. Then starting from the 2nd rightmost digit, the digit is multiplied by 2 then added to tsum, with every other digit doing the same. Then, the last line will check the rightmost digit of the current tsum and will tell me if the card is valid according to Luhn's Algorithm.
Here is what I usually do if I "try to implement" something I am not sure about: I use an interactive language, such as Common Lisp, tinker and test interactively until it works. Then, I usually have some good template I can use to write it in a less powerful language such as C.
(defun luhn-method (n)
(mod
(loop
for x = n then (floor x 10)
while (> x 0)
for double = nil then (not double)
for digit = (mod x 10)
for factor = (if double 2 1)
for y = (let ((a (* digit factor)))
(if (> a 9) (- a 9) a))
do (format t "~%~a" (list :x x :double double :digit digit :factor factor :y y))
summing y)
10))
I did this just from reading the wikipedia page about Luhn method (the german wiki page is easier to understand because it shows a simple exampple, while being less verbose than the english version).
From your Paypal site, the first number produces
(luhn-method 378282246310005)
(X 378282246310005 DOUBLE NIL DIGIT 5 FACTOR 1 Y 5)
(X 37828224631000 DOUBLE T DIGIT 0 FACTOR 2 Y 0)
(X 3782822463100 DOUBLE NIL DIGIT 0 FACTOR 1 Y 0)
(X 378282246310 DOUBLE T DIGIT 0 FACTOR 2 Y 0)
(X 37828224631 DOUBLE NIL DIGIT 1 FACTOR 1 Y 1)
(X 3782822463 DOUBLE T DIGIT 3 FACTOR 2 Y 6)
(X 378282246 DOUBLE NIL DIGIT 6 FACTOR 1 Y 6)
(X 37828224 DOUBLE T DIGIT 4 FACTOR 2 Y 8)
(X 3782822 DOUBLE NIL DIGIT 2 FACTOR 1 Y 2)
(X 378282 DOUBLE T DIGIT 2 FACTOR 2 Y 4)
(X 37828 DOUBLE NIL DIGIT 8 FACTOR 1 Y 8)
(X 3782 DOUBLE T DIGIT 2 FACTOR 2 Y 4)
(X 378 DOUBLE NIL DIGIT 8 FACTOR 1 Y 8)
(X 37 DOUBLE T DIGIT 7 FACTOR 2 Y 5)
(X 3 DOUBLE NIL DIGIT 3 FACTOR 1 Y 3)
0
making it easy to see every single step of the algorithm and convincing yourself it is correct.
To port this to C, first we need to explore, if C has an integer type wide enough for those credit card numbers (lisp has large integers by default - one thing less to worry about in our prototype). Lisp again:
(log 378282246310005 2)
48.426456
So, we need a 64 bit variable and should be good.
Since integers in C are implementation/platform/system specific, we should use some header file, giving us the correct type:
#include <stdint.h>
In there, the 64 bit unsigned integer is defined as uint64_t and if your compiler and your header files are correct for your system, using that makes sure, you do not get it wrong. The native "unsigned long long" etc. are just guesswork and not portable.
With that in place, we can simply port the code above to C:
uint64_t luhn(uint64_t n) {
uint64_t x = n;
uint64_t sum = 0;
uint64_t factor = 1;
while (x > 0) {
uint64_t y = (x % 10) * factor;
if (y > 9)
y = y - 9;
sum += y;
x = x / 10;
if (1 == factor) {
factor = 2;
} else {
factor = 1;
}
}
return sum % 10;
}
Summary:
A proper tool set helps getting stuff done. If you don't know yet, how to use a C debugger and step through code line by line while watching the content of variables, an interactive programming language is probably easier for you for prototyping.
Thank you for your help, I was able to solve this issue as it seems I had missed a step in Luhn's Algorithm.
//Luhn's Algorithm
int tsum = 0;
int luhn;
if (count % 2 != 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 != 0)
{
luhn = (cardNum % 10);
tsum += luhn;
}
else
{
luhn = (cardNum % 10) * 2;
if (luhn > 9)
{
tsum += (luhn - 9);
}
else
{
tsum += luhn;
}
}
cardNum /= 10;
}
}
else if (count % 2 == 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 == 0)
{
luhn = (cardNum % 10);
tsum += luhn;
}
else
{
luhn = (cardNum % 10) * 2;
if (luhn > 9)
{
tsum += (luhn - 9);
}
else
{
tsum += luhn;
}
}
cardNum /= 10;
}
}
tsum %= 10;
Here, I defined luhn as the next integer to be added to the tsum, in doing this I was able to fill in the missing step by subtracting 9 before adding to tsum if luhn exceeded 9.
Hi i am an amateur in programing, but i propose me to getting better and because that i start to solve problems in online judges and i don't know how to do a combinatorial analysis, i found some similar question but i can't apply to my code, if you are able to explain me how to do it, i will be incredibly grateful.
so here is the full text of the problem, translated of Portuguese to English. At end is my code.
To prove her scientific skills Princess Bubblegum learned to program using BMO (The best computer in the Candy kingdom) and like every programmer she fell in love with binary numbers.
Because of her addiction to binary numbers she loves decimal numbers that look like a binary number (i.e. a decimal number that contains only digits 0 and 1, for example 101) so given a decimal number N she wants to find a multiple of that number that looks like a number binary, but for some numbers it was taking a long time to find that multiple, even with the help of BMO. Because of her problem-solving addiction, she wasn't doing anything until she found this multiple. Perfect situation for the Earl of Lemongrab, who has taken over the Candy Kingdom. As Finn and Jake, the heroes of the Candy kingdom, can't do anything against the Count and know nothing about multiples, they asked to find the multiples and thus save the kingdom.
Prohibited
The input contains up to 2*10^5 lines, each line with an integer N (0 < N < 10^12), the number Princess Bubblegum wants to find the multiple M (M != 0), this number must be smaller than 10^12, otherwise it doesn't fit in the BMO architecture.
Exit
Print a single integer per line, if there are multiple multiples print the smallest one. If there is no solution print -1
#include <stdlib.h>
#include <math.h>
int main() // normal ways works fine but i have to do it faster, time limit is 2s//
//doing 11 fors works to but its have same tle problem//
{
long long int n, R, num, res, expo;
int b = 0, dig[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, E=0, an, anmax = 1024, reseter, cob, casa;
while (E < 200000)
{
E++;
num = 0;
scanf("%lld", &n); //I have to read a decimal number and from that found the smaller multiple number that is similar to a binary number, and cannot be 0//
res=n%10;
if ((res==1) || (res==0)) // in case the read number is already similar to binary, this works fine//
{ b=1;
for ( num=n;((num>0) && (b==1)); num=num/10)
{
res=num%10;
if ((res==1) || (res==0)){
b=1;
R=n;
}else
{
b=0;
R=-1;
}
}
}else{
if ((n > 0) && (n < 1000000000000))
{
if (n < 500000000000)
{
num = n;
for (expo = -1; num >= 1; expo++, num = num / 10)//so expo is a varieble to found the smaller house of input to made a number, its just for reduce cycles//
{
res = num % 10;
}
if (res > 1)
{
expo = expo + 1;
}
dig[expo] = 1;
R = ((dig[11] * 100000000000) + (dig[10] * 10000000000) + (dig[9] * 1000000000) + (dig[8] * 100000000) + (dig[7] * 10000000) + (dig[6] * 1000000) + (dig[5] * 100000) + (dig[4] * 10000) + (dig[3] * 1000) + (dig[2] * 100) + (dig[1] * 10) + (dig[0] * 1));
for (dig[expo] = 1; ((expo < 11) && (b == 0)); expo++)//// 1 is fixed value until no one of numbers is divisible//
{
anmax = pow(2, expo);//forget this line//
dig[expo] = 1;
for (casa = 0; ((casa < expo) && (b == 0)); casa++)//here is my problem i dont know how to alternate all values that can be ninary//
{ //this is my original idea to solve but this don't generate all possible values//
for (cob = 0; ((cob < 2) && (b == 0)); cob++)
{
dig[casa] = cob;
R = ((dig[11] * 100000000000) + (dig[10] * 10000000000) + (dig[9] * 1000000000) + (dig[8] * 100000000) + (dig[7] * 10000000) + (dig[6] * 1000000) + (dig[5] * 100000) + (dig[4] * 10000) + (dig[3] * 1000) + (dig[2] * 100) + (dig[1] * 10) + (dig[0] * 1));
if ((R % n) == 0)
{
b = 1;
}
}
}
if ((cob == 2) || (b==1))
{
for (reseter = expo; reseter >= 0; reseter--)//it works fine is just to start all values with 0 before its repeats//
{
dig[reseter] = 0;
}
}
}
}
else
{
R = -1;
}
if((R==11111111111) && ((n!=21649) || (n!=513239))){
R=-1; //its not important//
}
}else
{
R=-1;
}
}
// reset para proximos valores//
b = 0;
printf("%lld\n", R);
}
return 0;
}
I have basically no coding experience and am enrolled in CS50x on edX. I am currently working on Problem Set 1's Credit problem (in the C language). My program uses Luhn's Algorithm to determine whether a credit card number belongs to American Express, MasterCard, or Visa. When I test the program, inputing test credit card numbers gives me responses I don't want; every valid (test) credit card number I input gives no output.
I've been fighting with this for a few days. There was a point where my program recognized all 3 credit card company numbers, but allowed any random number to be inputted, while I wanted the program to print "INVALID" if that was the case.
Another problem I've had is getting an error for my integer variable, digitcount, (see code below) not being declared as a variable in one line of code (even though there are a few lines of code where digitcount is recognized just fine?)
I had fixed some of these bugs by reading into the error messages I got, but sometimes I can't understand them and just messing around ends up fixing them. It makes no sense to me. (Such as deleting or moving parenthesis and interchanging == with =.)
I have also tried looking at other peoples' codes, but when I try to use similar concepts to what I see, my program doesn't work.
Sorry if any of this is messy or hard to read! Even though I've been trying to teach myself what I need to know to make this work, I often get confused when using variable names like "n" and need some separation between certain parts of the code so I don't feel unorganized.
I could just skip Credit since I've done all the other problems in Problem Set 1, but I really want to learn and use any knowledge I come across to complete and understand as much as I can.
Here's my code! Many thanks to anyone who decides to take a look and help me understand where I'm wrong!
#include <cs50.h>
#include <math.h>
int main(void)
{
long long CCnumber;
//prompts the user for a credit card number
do
{
CCnumber = get_long_long("Enter your Credit Card Number: ");
}
while (CCnumber < 0);
//--------------------
//defines counter as a long type variable and digitcount as an integer type variable
int counter = 0;
int digitcount = 0;
//loop the counts the digit-length of the credit card number
while (counter > 0)
{
counter = CCnumber / 10;
digitcount++;
}
//--------------------
//grabs every other digit in the credit card number, starting from the second to last digit
//% grabs the remainder of a number divided, while / grabs the quotient of the number divided
int digit1 = (((CCnumber % 100) / 10) * 2);
int digit1a = (digit1 / 10);
int digit1b = (digit1 % 10);
int digit2 = (((CCnumber % 10000) / 1000) * 2);
int digit2a = (digit1 / 10);
int digit2b = (digit1 % 10);
int digit3 = (((CCnumber % 1000000) / 100000) * 2);
int digit3a = (digit1 / 10);
int digit3b = (digit1 % 10);
int digit4 = (((CCnumber % 100000000) / 10000000) * 2);
int digit4a = (digit1 / 10);
int digit4b = (digit1 % 10);
int digit5 = (((CCnumber % 10000000000) / 1000000000) * 2);
int digit5a = (digit1 / 10);
int digit5b = (digit1 % 10);
int digit6 = (((CCnumber % 1000000000000) / 100000000000) * 2);
int digit6a = (digit1 / 10);
int digit6b = (digit1 % 10);
int digit7 = (((CCnumber % 100000000000000) / 10000000000000) * 2);
int digit7a = (digit1 / 10);
int digit7b = (digit1 % 10);
int digit8 = (((CCnumber % 10000000000000000) / 1000000000000000) * 2);
int digit8a = (digit1 / 10);
int digit8b = (digit1 % 10);
//adds all the digits together
int checksum1 = (digit1a + digit1b + digit2a + digit2b + digit3a + digit3b + digit4a + digit4b + digit5a + digit5b + digit6a + digit6b +digit7a +digit7b + digit8a +digit8b);
//grabs all the other digits from the credit card number
int otherdigit1 = ((CCnumber % 10) / 1);
int otherdigit2 = ((CCnumber % 1000) / 100);
int otherdigit3 = ((CCnumber % 100000) / 10000);
int otherdigit4 = ((CCnumber % 10000000) / 1000000);
int otherdigit5 = ((CCnumber % 1000000000) / 100000000);
int otherdigit6 = ((CCnumber % 100000000000) / 10000000000);
int otherdigit7 = ((CCnumber % 10000000000000) / 1000000000000);
int otherdigit8 = ((CCnumber % 1000000000000000) / 100000000000000);
//adds all the other digits together
int checksum2 = (otherdigit1 + otherdigit2 + otherdigit3 + otherdigit4 + otherdigit5 + otherdigit6 + otherdigit7 + otherdigit8);
//adds the checksum halfs together
int TOTALchecksum = (checksum1 + checksum2);
//checks the last digit of the total checksum
int lastdigit = (TOTALchecksum / 1);
//--------------------
//determines what the credit card number's first and second digits are (15-digit count)
int startingdigit115 = (CCnumber / 100000000000000);
int startingdigit215 = ((CCnumber / 10000000000000) % 10);
int startingdigitsum15 = (startingdigit115 + startingdigit215);
//determines what the credit card number's first and second digits are (16-digit count)
int startingdigit116 = (CCnumber / 1000000000000000);
int startingdigit216 = ((CCnumber / 100000000000000) % 10);
int startingdigitsum16 = (startingdigit116 + startingdigit216);
//determines what the cred card number's first and second digits are (13-digit count)
int startingdigit113 = (CCnumber / 1000000000000);
int startingdigit213 = ((CCnumber / 100000000000) % 10);
int startingdigitsum13 = (startingdigit113 + startingdigit213);
//--------------------
if ((lastdigit == 0) && (digitcount == 15))
{
//determines if credit card number belongs to American Express
if (startingdigitsum15 == 7 || startingdigitsum15 == 10)
{
printf("AMEX\n");
}
}
else if ((lastdigit == 0) && (digitcount == 16))
{
//determines if credit card number belongs to MasterCard
if (startingdigitsum16 == 6 || startingdigitsum16 == 7 || startingdigitsum16 == 8 || startingdigitsum16 == 9 || startingdigitsum16 == 10)
{
printf("MASTERCARD\n");
}
}
else if ((lastdigit == 0 && digitcount == 13) || (lastdigit == 0 && digitcount == 16))
{
//determines if credit card number belongs to Visa
if ((startingdigit113 == 4 || startingdigit116 == 4))
{
printf("VISA\n");
}
}
else if ((lastdigit == 0 && digitcount != 13) || (lastdigit == 0 && digitcount != 15) || (lastdigit == 0 && digitcount != 16))
{
printf("INVALID\n");
}
}```
Counting leading zeroes is a little hard with numeric input. Maybe you should read the card number as string into a char * array using scanf; then, validate the CCNumber.
...
...
...
// max CCNumber char length is 16, plus 1 for string terminator '\0' = 17 chars
char CCNumber[17];
int notValidInput = 1;
int digitCount = 0;
while (notValidInput) {
notValidInput = 0;
scanf("%s", CCNumber);
digitCount = 0;
while (CCNumber[digitCount] != '\0') {
// CCNumber character validation
if (CCNumber[digitCount] < '0' || CCNumber[digitCount] > '9') {
notValidInput = 1;
printf("error: must contain numeric chars.\n");
break;
}
else {
digitCount++;
}
}
...
...
...
}
#include <stdio.h>
#include <cs50.h>
int main(void)
{
long cc = get_long("Credit Card: "); // gets input
long len = 0; //intialized length
long x = cc; // set 2nd variable = to cc to prevent manipulation of cc
while (x != 0) // length count loop while x is divisable loop will continue will be stored as len
{
x = x / 10;
len++;
}
if ((len != 16) && (len != 15) && (len != 13)) //Checking for length to see if number matchs possible postive outcomes
{
printf("INVALID\n");
return 0;
}
//pull 2nd to last and then every other digit
long cc_num1 = ((cc % 100) / 10);
long cc_num2 = ((cc % 10000) / 1000);
long cc_num3 = ((cc % 1000000) / (100000));
long cc_num4 = ((cc % 100000000) / (10000000));
long cc_num5 = ((cc % 10000000000) / (1000000000));
long cc_num6 = ((cc % 1000000000000) / (100000000000));
long cc_num7 = ((cc % 100000000000000) / (10000000000000));
long cc_num8 = ((cc % 10000000000000000) / (1000000000000000));
cc_num1 = (cc_num1 * 2); //Multiply digits pulled above by 2
cc_num2 = (cc_num2 * 2);
cc_num3 = (cc_num3 * 2);
cc_num4 = (cc_num4 * 2);
cc_num5 = (cc_num5 * 2);
cc_num6 = (cc_num6 * 2);
cc_num7 = (cc_num7 * 2);
cc_num8 = (cc_num8 * 2);
cc_num1 = ((cc_num1 / 10) + (cc_num1 % 10)); //split double digits and add to signles
cc_num2 = ((cc_num2 / 10) + (cc_num2 % 10));
cc_num3 = ((cc_num3 / 10) + (cc_num3 % 10));
cc_num4 = ((cc_num4 / 10) + (cc_num4 % 10));
cc_num5 = ((cc_num5 / 10) + (cc_num5 % 10));
cc_num6 = ((cc_num6 / 10) + (cc_num6 % 10));
cc_num7 = ((cc_num7 / 10) + (cc_num7 % 10));
cc_num8 = ((cc_num8 / 10) + (cc_num8 % 10));
long cc_sum = cc_num1 + cc_num2 + cc_num3 + cc_num4 + cc_num5 + cc_num6 + cc_num7 + cc_num8; // add sum of number above
long cc_num1x = ((cc % 10) / 1); //pulls last digit from card then everyother digit
long cc_num2x = ((cc % 1000) / 100);
long cc_num3x = ((cc % 100000) / 10000);
long cc_num4x = ((cc % 10000000) / 1000000);
long cc_num5x = ((cc % 1000000000) / 100000000);
long cc_num6x = ((cc % 100000000000) / 10000000000);
long cc_num7x = ((cc % 10000000000000) / 1000000000000);
long cc_num8x = ((cc % 1000000000000000) / 100000000000000);
long cc_sumx = cc_num1x + cc_num2x + cc_num3x + cc_num4x + cc_num5x + cc_num6x + cc_num7x +
cc_num8x; //adds last and everyother digit together
long sumofsums = cc_sum + cc_sumx; // adds sums of both sums created
if ((sumofsums % 10) != 0) // Luhn’s Algorithm results will close if not met
{
printf("INVALID\n");
return 0;
}
{
if (len == 15) // checks for AMEX by using length then first 2 digits
{
long ax = cc / 10000000000000;
if ((ax == 34 || ax == 37))
{
printf("AMEX\n");
}
else
{
printf("INVALID\n");
return 0;
}
}
}
long mc = cc / 100000000000000;
long v = cc / 1000000000000000;
long v2 = cc / 1000000000000;
if (len == 16) // Checks for MC and Via (16 digits) by length then first 2 digits MC or 1 visa
{
if ((mc == 51 || mc == 52 || mc == 53 || mc == 54 || mc == 55))
{
printf("MASTERCARD\n");
}
else if (v == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
return 0;
}
}
if (len == 13) //Checks 2nd Visa length 13 digits then 1st digit
{
if (v2 == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
return 0;
}
}
}
There has to be a better way then the way I am planning to do this. The Length count loop is fine until 10 digits but then pulls random numbers.
The every other digit formula seems like it can be done through recursion but I am blanking on that. Since the number is limited to 16 at most the formula I am using seems to work.
Determine if card is 15 || 16 || 13 digits if not mark In valid in IF Else loop
Use CC check sum formula If else loop (In valid if it doesn't meet Criteria)
Look at 2 Starting numbers to determine AX, MC or Visa
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int main(void)
{
long cc = get_long("Credit Card: " ); // gets input
int len = 0; //intialized length
int x = cc; // set 2nd variable = to cc to prevent manipulation of cc
while(x != 0) // length count loop while x is divisable loop will continue will be stored as len
{
x = x/10;
len++;
}
printf("%i\n", len); // REMOVE !!!!!!!!!!! BUG TEST
//pull 2nd to last and then every other digit
int cc_num1 = ((cc % 100)/10);
int cc_num2 = ((cc % 10000)/1000);
int cc_num3 = ((cc % 1000000)/(100000));
int cc_num4 = ((cc % 100000000)/(10000000));
int cc_num5 = ((cc % 10000000000)/(1000000000));
int cc_num6 = ((cc % 1000000000000)/(100000000000));
int cc_num7 = ((cc % 100000000000000)/(10000000000000));
int cc_num8 = ((cc % 10000000000000000)/(1000000000000000));
printf("%i %i %i %i %i %i %i %i", cc_num1, cc_num2, cc_num3, cc_num4 , cc_num5, cc_num6 , cc_num7 , cc_num8 );
}
Let's acknowledge the elephant in the room first.
long cc = get_long("Credit Card: " );
...
int x = cc;
The C standard specifies long to be at least 32 bits, whereas int must be at least 16 bits. The actual values are dependent on your system and your library implementation of course. But more often than not, long will be capable of storing more bits than an int. As is the case here. This means "numbers with more than 10 digits", essentially numbers that are too large to be stored into an int, will cause undefined behavior. To know exactly which number is the upper limit for int in your system/environment, you may print the value of INT_MAX, defined in limits.h.
The solution is, of course, to store the long variable in another long variable, not an int. Or, simply pass the value to a function that does the necessary work. Putting everything in main isn't being very organized now is it.
How about we make a function that basically prints all the details about a card given the card's number?
The signature will look like-
void print_card_details(long num)
Now we need a function to put the card through luhn's algorithm. We can also make a function for that-
int is_valid(long num)
{
int curr_digit, add_digit, prod_sum = 0, sum = 0;
for (int digit_count = 0; num != 0; num /= 10, digit_count++)
{
// Strip each digit from number, starting from the end
curr_digit = num % 10;
if (digit_count % 2 != 0)
{
// Every 2nd digit from the right goes through this
// The current digit gets doubled
// The digits of that result are added to the sum
add_digit = curr_digit * 2;
prod_sum += add_digit % 10 + add_digit / 10;
}
else
{
// The remaining digits go through this
// They are all summed up
sum += curr_digit;
}
}
if ((prod_sum + sum) % 10 != 0)
{
// If the sum of prod_sum + sum doesn't end in 0
// It is invalid
return 0;
}
else
{
// The card is valid
return 1;
}
}
The conventional way to iterate through the digits of a number is not to bruteforcefully divide arbitrary powers of 10 manually, but to iterate through it and divide and modulus by 10. For example, this snippet-
while (x != 0)
{
printf("Current digit: %d\n", x % 10);
x /= 10;
}
Will print all digits of the number stored in x. This is essentially what we've used in the luhn's algorithm loop. Except we also keep a count of the total digits, because we only want every second digit starting from the end. How do we know the current digit qualifies this criteria? We check if the current digit_count is even (by dividing by 2 and checking the leftover is 0).
The formula that follows-
add_digit = curr_digit * 2;
prod_sum += add_digit % 10 + add_digit / 10;
is basically the implementation of this-
Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together.
Make sure only the digits of the resulting add_digit is added. So if add_digit ended up being 12. We need to add 1 + 2. That's exactly what add_digit % 10 + add_digit / 10 does. 12 % 10 is, of course, 2. And 12 / 10 is 1.
This function returns 1 if the card is valid, 0 if it's not. You can fit this up in your main function and check the return value to know whether the card is valid.
If it is valid, move on to the next step of checking the number of digits the card has, as well as what it begins with.
We can make a loop to count the number of digits, as well as store the very first and second digit of the number.
int len = 0;
int curr_digit = 0, prev_digit = 0;
while(num != 0)
{
prev_digit = curr_digit;
curr_digit = num % 10;
num /= 10;
len++;
}
This will give you the length of the card number. Notice, in the last iteration, the value of prev_digit is the second digit and the curr_digit is the first. So curr_digit * 10 + prev_digit will yield the first 2 numbers (together) that the credit card number begins with.
Finally, you just need a bunch of simple if/else clauses to verify which card it is. You're only asked to check for a very small subset as well. So here it is-
// Construct the 2 digit number that this card num begins with
int begins_with = curr_digit * 10 + prev_digit;
if (len == 13 && begins_with / 10 == 4)
{
// We know only VISA uses 13 digits
// And it begins with 4 (second digit does not matter)
printf("VISA\n");
}
else if (len == 15 && begins_with == 34 ||)
{
// We know only AMEX uses 15 digits
printf("AMEX\n");
}
else if (len == 16)
{
// Both VISA and MASTERCARD use 16 digits
if (curr_digit == 4)
{
// But VISA card number begins with 4
printf("VISA\n");
}
else if (curr_digit == 5)
{
// MASTERCARD number begins with 5
printf("MASTERCARD\n");
}
else
{
// Out of context for this problem
printf("INVALID\n");
}
}
else
{
// Out of context for this problem
printf("INVALID\n");
}
Put that all together, and you should hopefully get
void print_card_details(long num)
{
if (!is_valid(num))
{
// Card did not pass luhn's algo
printf("INVALID\n");
return;
}
int len = 0;
int curr_digit = 0, prev_digit = 0;
while(num != 0)
{
prev_digit = curr_digit;
curr_digit = num % 10;
num /= 10;
len++;
}
// Construct the 2 digit number that this card num begins with
int begins_with = curr_digit * 10 + prev_digit;
if (len == 13 && curr_digit == 4)
{
// We know only VISA uses 13 digits
// And it begins with 4 (second digit does not matter)
printf("VISA\n");
}
else if (len == 15 && (begins_with == 34 || begins_with == 37))
{
// We know only AMEX uses 15 digits
printf("AMEX\n");
}
else if (len == 16)
{
// Both VISA and MASTERCARD use 16 digits
if (curr_digit == 4)
{
// But VISA card number begins with 4
printf("VISA\n");
}
else if (begins_with >= 51 && begins_with <= 55)
{
// MASTERCARD number begins with 51, 52, 53, 54, or 55
printf("MASTERCARD\n");
}
else
{
// Out of context for this problem
printf("INVALID\n");
}
}
else
{
// Out of context for this problem
printf("INVALID\n");
}
return;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm looking to implement an FFT algorithm on microcontrollers so I want to simulate the codes before actually using it
I got 2 examples which I converted to matlab codes but the result just isn't what I'm expected
Here are the codes:
function [ H ] = fft_2( g )
%FFT2 Summary of this function goes here
% Detailed explanation goes here
NUMDATA = length(g);
NUMPOINTS = NUMDATA/2;
N = NUMPOINTS;
% for(k=0; k<N; k++)
% {
% IA[k].imag = -(short)(16383.0*(-cos(2*pi/(double)(2*N)*(double)k)));
% IA[k].real = (short)(16383.0*(1.0 - sin(2*pi/(double)(2*N)*(double)k)));
% IB[k].imag = -(short)(16383.0*(cos(2*pi/(double)(2*N)*(double)k)));
% IB[k].real = (short)(16383.0*(1.0 + sin(2*pi/(double)(2*N)*(double)k)));
% }
for k=0:(N-1)
IA(k+1,2) = -floor(16383.0*(-cos(2*pi/(2*N)*k)));
IA(k+1,1) = floor(16383.0*(1.0 - sin(2*pi/(2*N)*k)));
IB(k+1,2) = -floor(16383.0*(cos(2*pi/(2*N)*k)));
IB(k+1,1) = floor(16383.0*(1.0 + sin(2*pi/(2*N)*k)));
end
% Note, IA(k) is the complex conjugate of A(k) and IB(k) is the complex conjugate of
% B(k).
% *********************************************************************************/
% #include <math.h>
% #include ”params1.h”
% #include ”params.h”
% extern short g[];
% void dft(int, COMPLEX *);
% void split(int, COMPLEX *, COMPLEX *, COMPLEX *, COMPLEX *);
% main()
% {
% int n, k;
% COMPLEX x[NUMPOINTS+1]; /* array of complex DFT data */
% COMPLEX A[NUMPOINTS]; /* array of complex A coefficients */
% COMPLEX B[NUMPOINTS]; /* array of complex B coefficients */
% COMPLEX IA[NUMPOINTS]; /* array of complex A* coefficients */
% COMPLEX IB[NUMPOINTS]; /* array of complex B* coefficients */
% COMPLEX G[2*NUMPOINTS]; /* array of complex DFT result */
% for(k=0; k<NUMPOINTS; k++)
for k=0:(NUMPOINTS-1)
% {
% A[k].imag = (short)(16383.0*(-cos(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% A[k].real = (short)(16383.0*(1.0 - sin(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% B[k].imag = (short)(16383.0*(cos(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% B[k].real = (short)(16383.0*(1.0 + sin(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% IA[k].imag = -A[k].imag;
% IA[k].real = A[k].real;
% IB[k].imag = -B[k].imag;
% IB[k].real = B[k].real;
% }
A(k+1, 2) = floor(16383.0*(-cos(2*pi/(2*NUMPOINTS)*k)));
A(k+1, 1) = floor(16383.0*(1.0 - sin(2*pi/(2*NUMPOINTS)*k)));
B(k+1, 2) = floor(16383.0*(cos(2*pi/(2*NUMPOINTS)*k)));
B(k+1, 1) = floor(16383.0*(1.0 + sin(2*pi/(2*NUMPOINTS)*k)));
IA(k+1, 2) = -A(k+1, 2);
IA(k+1, 1) = A(k+1, 1);
IB(k+1, 2) = -B(k+1, 2);
IB(k+1, 1) = B(k+1, 1);
end
% /* Forward DFT */
% /* From the 2N point real sequence, g(n), for the N-point complex sequence, x(n) */
% for (n=0; n<NUMPOINTS; n++)
% {
for n=0:(NUMPOINTS-1)
% x[n].imag = g[2*n + 1]; /* x2(n) = g(2n + 1) */
% x[n].real = g[2*n]; /* x1(n) = g(2n) */
% }
x(n+1,2)=g(2*n + 1+1);
x(n+1,1)=g(2*n +1);
end
% /* Compute the DFT of x(n) to get X(k) -> X(k) = DFT{x(n)} */
% dft(NUMPOINTS, x);
% void dft(int N, COMPLEX *X)
% {
% int n, k;
% double arg;
% int Xr[1024];
% int Xi[1024];
% short Wr, Wi;
% for(k=0; k<N; k++)
% {
N=NUMPOINTS;
for k=0:(N-1)
% Xr[k] = 0;
% Xi[k] = 0;
Xr(k+1)=0;
Xi(k+1)=0;
% for(n=0; n<N; n++)
% {
for n=0:(N-1)
% arg =(2*PI*k*n)/N;
% Wr = (short)((double)32767.0 * cos(arg));
% Wi = (short)((double)32767.0 * sin(arg));
% Xr[k] = Xr[k] + X[n].real * Wr + X[n].imag * Wi;
% Xi[k] = Xi[k] + X[n].imag * Wr – X[n].real * Wi;
arg = (2*pi*k*n)/N;
Wr = floor(32767*cos(arg));
Wi = floor(32767*sin(arg));
Xr(k+1) = Xr(k+1)+x(n+1,1)*Wr+x(n+1,2)*Wi;
Xi(k+1) = Xr(k+1)+x(n+1,2)*Wr-x(n+1,1)*Wi;
% }
% }
end
end
% for (k=0;k<N;k++)
% {
for k=0:(N-1)
% X[k].real = (short)(Xr[k]>>15);
% X[k].imag = (short)(Xi[k]>>15);
x(k+1,1)=floor(Xr(k+1)/pow2(15));
x(k+1,2)=floor(Xi(k+1)/pow2(15));
% }
% }
end
% /* Because of the periodicity property of the DFT, we know that X(N+k)=X(k). */
% x[NUMPOINTS].real = x[0].real;
% x[NUMPOINTS].imag = x[0].imag;
x(NUMPOINTS+1,1)=x(1,1);
x(NUMPOINTS+1,2)=x(1,2);
% /* The split function performs the additional computations required to get
% G(k) from X(k). */
% split(NUMPOINTS, x, A, B, G);
% void split(int N, COMPLEX *X, COMPLEX *A, COMPLEX *B, COMPLEX *G)
% {
% int k;
% int Tr, Ti;
% for (k=0; k<N; k++)
% {
for k=0:(NUMPOINTS-1)
% Tr = (int)X[k].real * (int)A[k].real – (int)X[k].imag * (int)A[k].imag +
% (int)X[N–k].real * (int)B[k].real + (int)X[N–k].imag * (int)B[k].imag;
Tr = x(k+1,1)*A(k+1,1)-x(k+1,2)*A(k+1,2)+x(NUMPOINTS-k+1,1)*B(k+1,1)+x(NUMPOINTS-k+1,2)*B(k+1,2);
% G[k].real = (short)(Tr>>15);
G(k+1,1)=floor(Tr/pow2(15));
% Ti = (int)X[k].imag * (int)A[k].real + (int)X[k].real * (int)A[k].imag +
% (int)X[N–k].real * (int)B[k].imag – (int)X[N–k].imag * (int)B[k].real;
Ti = x(k+1,2)*A(k+1,1)+x(k+1,1)*A(k+1,2)+x(NUMPOINTS-k+1,1)*B(k+1,2)-x(NUMPOINTS-k+1,2)*B(k+1,1);
% G[k].imag = (short)(Ti>>15);
G(k+1,2)=floor(Ti/pow2(15));
% }
end
% }
% /* Use complex conjugate symmetry properties to get the rest of G(k) */
% G[NUMPOINTS].real = x[0].real - x[0].imag;
% G[NUMPOINTS].imag = 0;
% for (k=1; k<NUMPOINTS; k++)
% {
% G[2*NUMPOINTS-k].real = G[k].real;
% G[2*NUMPOINTS-k].imag = -G[k].imag;
% }
G(NUMPOINTS+1,1) = x(1,1) - x(1,2);
G(NUMPOINTS+1,2) = 0;
for k=1:(NUMPOINTS-1)
G(2*NUMPOINTS-k+1,1) = G(k+1,1);
G(2*NUMPOINTS-k+1,2) = -G(k+1,2);
end
for k=1:(NUMDATA)
H(k)=sqrt(G(k,1)*G(k,1)+G(k,2)*G(k,2));
end
end
Another one:
function [ fr, fi ] = fix_fft( fr, fi )
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
N_WAVE = 1024; % full length of Sinewave[]
LOG2_N_WAVE = 10; % log2(N_WAVE)
m = nextpow2(length(fr));
% void fix_fft(short fr[], short fi[], short m)
% {
% long int mr = 0, nn, i, j, l, k, istep, n, shift;
mr=0;
% short qr, qi, tr, ti, wr, wi;
%
% n = 1 << m;
n = pow2(m);
% nn = n - 1;
nn = n-1;
%
% /* max FFT size = N_WAVE */
% //if (n > N_WAVE) return -1;
%
% /* decimation in time - re-order data */
% for (m=1; m<=nn; ++m)
for m=1:nn
% {
% l = n;
l=n;
% do
% {
% l >>= 1;
% } while (mr+l > nn);
not_done = true;
while(mr+l>nn || not_done)
l=floor(l/2);
not_done=false;
end
%
% mr = (mr & (l-1)) + l;
mr = (mr & (l-1)) + l;
% if (mr <= m) continue;
if (mr <= m)
continue
end
%
% tr = fr[m];
% fr[m] = fr[mr];
% fr[mr] = tr;
% ti = fi[m];
% fi[m] = fi[mr];
% fi[mr] = ti;
tr = fr(m+1);
fr(m+1) = fr(mr+1);
fr(mr+1) = tr;
ti = fi(m+1);
fi(m+1) = fi(mr+1);
fi(mr+1) = ti;
% }
end
%
% l = 1;
% k = LOG2_N_WAVE-1;
l=1;
k = LOG2_N_WAVE-1;
%
% while (l < n)
% {
while (l < n)
% /*
% fixed scaling, for proper normalization --
% there will be log2(n) passes, so this results
% in an overall factor of 1/n, distributed to
% maximize arithmetic accuracy.
%
% It may not be obvious, but the shift will be
% performed on each data point exactly once,
% during this pass.
% */
%
% // Variables for multiplication code
% long int c;
% short b;
%
% istep = l << 1;
istep = l*2;
% for (m=0; m<l; ++m)
% {
for m=0:(l-1)
% j = m << k;
% /* 0 <= j < N_WAVE/2 */
% wr = Sinewave[j+N_WAVE/4];
% wi = -Sinewave[j];
j = m*(pow2( k));
wr = sin((j+N_WAVE/4)*2*pi/N_WAVE)*32768;
wi = -sin(j*2*pi/1024)*32768;
%
% wr >>= 1;
% wi >>= 1;
wr = floor(wr/2);
wi = floor(wi/2);
%
% for (i=m; i<n; i+=istep)
% {
i=m;
while(i<n)
% j = i + l;
j = i+l;
%
% // Here I unrolled the multiplications to prevent overhead
% // for procedural calls (we don't need to be clever about
% // the actual multiplications since the pic has an onboard
% // 8x8 multiplier in the ALU):
%
% // tr = FIX_MPY(wr,fr[j]) - FIX_MPY(wi,fi[j]);
% c = ((long int)wr * (long int)fr[j]);
% c = c >> 14;
% b = c & 0x01;
% tr = (c >> 1) + b;
c = wr * fr(j+1);
c = floor(c / pow2(14));
b = c & 1;
tr = floor(c /2) + b;
%
% c = ((long int)wi * (long int)fi[j]);
% c = c >> 14;
% b = c & 0x01;
% tr = tr - ((c >> 1) + b);
c = wi * fi(j+1);
c = floor(c / pow2(14));
b = c & 1;
tr = tr - (floor((c/2)) + b);
%
% // ti = FIX_MPY(wr,fi[j]) + FIX_MPY(wi,fr[j]);
% c = ((long int)wr * (long int)fi[j]);
% c = c >> 14;
% b = c & 0x01;
% ti = (c >> 1) + b;
c = wr*fi(j+1);
c = floor(c / pow2(14));
b = c & 1;
ti = floor((c /2)) + b;
%
% c = ((long int)wi * (long int)fr[j]);
% c = c >> 14;
% b = c & 0x01;
% ti = ti + ((c >> 1) + b);
c = wi * fr(j+1);
c = floor(c / pow2(14));
b = c & 1;
ti = ti + (floor((c/2)) + b);
%
% qr = fr[i];
% qi = fi[i];
% qr >>= 1;
% qi >>= 1;
%
% fr[j] = qr - tr;
% fi[j] = qi - ti;
% fr[i] = qr + tr;
% fi[i] = qi + ti;
qr = fr(i+1);
qi = fi(i+1);
qr = floor(qr/2);
qi = floor(qi/2);
fr(j+1) = qr - tr;
fi(j+1) = qi - ti;
fr(i+1) = qr + tr;
fi(i+1) = qi + ti;
% }
i = i+istep;
end
% }
end
%
% --k;
% l = istep;
% }
k=k-1;
l=istep;
end
% }
end
Those in comments are the original, those aren't are the translated code
Then I simulated with this
function [ r ] = mfft( f )
%MFFT Summary of this function goes here
% Detailed explanation goes here
Fs = 2048;
T = 1/Fs;
L = 2048;
t = (0:L-1)*T;
NFFT = 2^nextpow2(L);
l = length(f);
y = 0;
for k=1:l
y = y + sin(2*pi*f(k)*t);
end
%sound(y, Fs);
Y = fft(y,NFFT)/L;
YY = fft_2(y)/L;
[Y1 Y2] = fix_fft(y, zeros(1, L));
YYY = Y1+j()*Y2;
f = Fs/2*linspace(0,1,NFFT/2+1);
plot(f, 2*abs(Y(1:NFFT/2+1)), ':+b');
hold on
plot(f, 2*abs(YY(1:NFFT/2+1)), '-or');
plot(f, abs(YYY(1:NFFT/2+1)), '--*g');
hold off
r=0;
end
Basically create a simple sine wave with a specific frequency (say 400Hz)
The expected output of the FFT should be a spike at 400 only, which the builtin FFT function agrees but the other codes didn't
Here's the output graph
The blue line is from builtin function and is what expected
The red line is the above code which, well, looks pretty good except there is a spike elsewhere with higher amplitude
The green line is absolute mess
I tried checking the program several times but to no avail
Did I ported them wrong or somehow I can fix them?
There are several ways to approach this problem, and a programmer should try all of them. First, an FFT is an optimization of a Fourier Transform, so as a first step code a Fourier Transform. That is, don't do an FFT, just do a FT directly.
These days an FT is not as slow as you might think. Unless the project needs to transform something like 10,000 data points in less than a few milliseconds. Also, an FT, compared to an FFT, is simple and easy to debug.
Doing this for a problem provides a baseline, that is, the correct answer. This is important because when you work on the FFT how do you know if the problem is in the code for the FFT or that the data is correct and just giving you an unexpected, but correct, answer.
Next, use a pre-written package to do an FFT. Scan the web, I know there are packages written in C that do FFTs.
Third, if you just have to write your own FFT then do so. But only if tasks (1) or (2) don't meet your requirements. It will be difficult to out-do any pre-written FFT packages.
You will learn much along this path.