Directions: Source Code: /* ----------- * bignum_math.c * Project for CSCI 2021,
ID: 3757476 • Letter: D
Question
Directions:
Source Code:
/* -----------
* bignum_math.c
* Project for CSCI 2021, Fall 2018, Professor Chris Dovolis
* orginially written by Andy Exley
* modified by Ry Wiese, Min Choi, Aaron Councilman
* ---------- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define false 0;
#define true 1;
typedef int bool;
/*
* Returns true if the given char is a digit from 0 to 9
*/
bool is_digit(char c) {
return c >= '0' && c <= '9';
}
/*
* Returns true if lower alphabetic character
*/
bool is_lower_alphabetic(char c) {
return c >= 'a' && c <= 'z';
}
/*
* Returns true if upper alphabetic character
*/
bool is_upper_alphabetic(char c) {
return c >= 'A' && c <= 'Z';
}
/*
* Convert a string to an integer
* returns 0 if it cannot be converted.
*/
int string_to_integer(char* input) {
int result = 0;
int length = strlen(input);
int num_digits = length;
int sign = 1;
int i = 0;
int factor = 1;
if (input[0] == '-') {
num_digits--;
sign = -1;
}
for (i = 0; i < num_digits; i++, length--) {
if (!is_digit(input[length-1])) {
return 0;
}
if (i > 0) factor*=10;
result += (input[length-1] - '0') * factor;
}
return sign * result;
}
/*
* Returns true if the given base is valid.
* that is: integers between 2 and 36
*/
bool valid_base(int base) {
if(!(base >= 2 && base <= 36)) {
return false;
}
return true;
}
/*
* TODO
* Returns true if the given string (char array) is a valid input,
* that is: digits 0-9, letters A-Z, a-z
* and it should not violate the given base and should not handle
negative numbers
*/
bool valid_input(char* input, int base) {
return true;
}
/*
* converts from an array of characters (string) to an array of integers
*/
int* string_to_integer_array(char* str) {
int* result;
int i, str_offset = 0;
result = malloc((strlen(str) + 1) * sizeof(int));
result[strlen(str)] = -1;
for(i = str_offset; str[i] != ''; i++) {
if(is_digit(str[i])) {
result[i - str_offset] = str[i] - '0';
} else if (is_lower_alphabetic(str[i])) {
result[i - str_offset] = str[i] - 'a' + 10;
} else if (is_upper_alphabetic(str[i])) {
result[i - str_offset] = str[i] - 'A' + 10;
} else {
printf("I don't know how got to this
point! ");
}
}
return result;
}
/*
* finds the length of a bignum...
* simply traverses the bignum until a negative number is found.
*/
int bignum_length(int* num) {
int len = 0;
while(num[len] >= 0) { len++; }
return len;
}
/*
* TODO
* Prints out a bignum using digits and lower-case characters
* Current behavior: prints integers
* Expected behavior: prints characters
*/
void bignum_print(int* num) {
int i;
if(num == NULL) { return; }
i = bignum_length(num);
/* Then, print each digit */
for(i = 0; num[i] >= 0; i++) {
printf("%d", num[i]);
}
printf(" ");
}
/*
* Helper for reversing the result that we built backward.
* see add(...) below
*/
void reverse(int* num) {
int i, len = bignum_length(num);
for(i = 0; i < len/2; i++) {
int temp = num[i];
num[i] = num[len-i-1];
num[len-i-1] = temp;
}
}
/*
* addition of input1 and input2
* PROVIDED FOR GUIDANCE
*/
int* add(int* input1, int* input2, int base) {
int len1 = bignum_length(input1);
int len2 = bignum_length(input2);
int resultlength = ((len1 > len2)? len1 : len2) + 2;
int* result = (int*) malloc (sizeof(int) * resultlength);
int r = 0;
int carry = 0;
int sign = input1[len1];
int num1, num2;
len1--;
len2--;
while (len1 >= 0 || len2 >= 0) {
if (len1 >= 0) {
num1 = input1[len1];
} else {
num1 = 0;
}
if (len2 >= 0) {
num2 = input2[len2];
} else {
num2 = 0;
}
result[r] = (num1 + num2 + carry) % base;
carry = (num1 + num2 + carry) / base;
len1--;
len2--;
r++;
}
if (carry > 0) {
result[r] = carry;
r++;
}
result[r] = sign;
reverse(result);
return result;
}
/*
* TODO
* return true if input1 < input2, and false otherwise
*/
bool less_than(int* input1, int* input2) {
return false;
}
/*
* TODO
* return true if input1 > input2, and false otherwise
*/
bool greater_than(int* input1, int* input2) {
return false;
}
/*
* TODO
* return true if input1 == input2, and false otherwise
*/
bool equal_to(int* input1, int* input2) {
return false;
}
/*
* TODO
* multiply input1 * input2
*/
int* multiply(int* input1, int* input2, int base) {
return NULL;
}
/*
* TODO
* This function is where you will write the code that performs the heavy
lifting,
* actually performing the calculations and comparisons on input1 and
input2.
* This function prints the result using printf. It does not return any
value.
* The text printed should always be of the form
* Result: ...
* Where the ... is either a number of one of 'true' or 'false'.
* See the project write-up for examples.
* HINT: For better code structure, use helper functions.
*/
void perform_operation(int* input1, int* input2, char op, int base) {
if(op == '+') {
int* result = add(input1, input2, base);
printf("Result: ");
bignum_print(result);
printf(" ");
free(result);
}
/*
* TODO
* Handle multiplication, less than, greater than, and equal to
*/
}
/*
* Print to "stderr" and exit program
*/
void print_usage(char* name) {
fprintf(stderr, "---------------------------------------------------
- ");
fprintf(stderr, "Usage: %s base input1 operation input2 ", name);
fprintf(stderr, "base must be number between 2 and 36,
inclusive ");
fprintf(stderr, "input1 and input2 are arbitrary-length
integers ");
fprintf(stderr, "Permited operations are allowed '+', '*', '<', '>',
and '=' ");
fprintf(stderr, "---------------------------------------------------
- ");
exit(1);
}
/*
* MAIN: Run the program and tests your functions.
* sample command: ./bignum 4 12 + 13
* Result: 31
*/
int main(int argc, char** argv) {
int input_base;
int* input1;
int* input2;
if(argc != 5) {
print_usage(argv[0]);
}
input_base = string_to_integer(argv[1]);
if(!valid_base(input_base)) {
fprintf(stderr, "Invalid base: %s ", argv[1]);
print_usage(argv[0]);
}
if(!valid_input(argv[2], input_base)) {
fprintf(stderr, "Invalid input1: %s ", argv[2]);
print_usage(argv[0]);
}
if(!valid_input(argv[4], input_base)) {
fprintf(stderr, "Invalid input2: %s ", argv[4]);
print_usage(argv[0]);
}
char op = argv[3][0];
if(op != '+' && op != '*' && op != '<' && op != '>' && op != '=') {
fprintf(stderr, "Invalid operation: %s ", argv[3]);
print_usage(argv[0]);
}
input1 = string_to_integer_array(argv[2]);
input2 = string_to_integer_array(argv[4]);
perform_operation(input1, input2, op, input_base);
free(input1);
free(input2);
exit(0);
}
Setup Download bignum_math.c from Canvas. You should now have a file named bignum_math.c with all of the function outlines Your task For this project, you will write a program that can perform comparison (>,Explanation / Answer
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define false 0;
#define true 1;
typedef int bool;
/*
* Returns true if the given char is a digit from 0 to 9
*/
bool is_digit(char c) {
return c >= '0' && c <= '9';
}
/*
* Returns true if lower alphabetic character
*/
bool is_lower_alphabetic(char c) {
return c >= 'a' && c <= 'z';
}
/*
* Returns true if upper alphabetic character
*/
bool is_upper_alphabetic(char c) {
return c >= 'A' && c <= 'Z';
}
/*
* Convert a string to an integer
* returns 0 if it cannot be converted.
*/
int string_to_integer(char* input) {
int result = 0;
int length = strlen(input);
int num_digits = length;
int sign = 1;
int i = 0;
int factor = 1;
if (input[0] == '-') {
num_digits--;
sign = -1;
}
for (i = 0; i < num_digits; i++, length--) {
if (!is_digit(input[length-1])) {
return 0;
}
if (i > 0) factor*=10;
result += (input[length-1] - '0') * factor;
}
return sign * result;
}
/*
* Returns true if the given base is valid.
* that is: integers between 2 and 36
*/
bool valid_base(int base) {
if(!(base >= 2 && base <= 36)) {
return false;
}
return true;
}
/*
* TODO
* Returns true if the given string (char array) is a valid input,
* that is: digits 0-9, letters A-Z, a-z
* and it should not violate the given base and should not handle negative numbers
*/
bool valid_input(char* input, int base) {
const char totalBaseValues[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char inputValidBaseValues[base+1];
// Get a char array of the valid characters for the given base
for (int i = 0; i < base; i++) {
inputValidBaseValues[i] = totalBaseValues[i];
}
inputValidBaseValues[base] = '';
// Iterate through input char array and check if in valid input char array
for (int j=0; j < strlen(input); j++) {
char element = inputValidBaseValues[j];
int invalidCharCounter = 0;
for (int k=0; k < base; k++) {
if (is_lower_alphabetic(input[j])) {
char ltr = toupper(input[j]);
if (ltr != inputValidBaseValues[k]) {
invalidCharCounter++;
}
} else if (input[j] != inputValidBaseValues[k]) {
invalidCharCounter++;
}
}
if (invalidCharCounter >= base) {
return false;
}
}
return true;
}
/*
* converts from an array of characters (string) to an array of integers
*/
int* string_to_integer_array(char* str) {
int* result;
int i, str_offset = 0;
result = malloc((strlen(str) + 1) * sizeof(int));
result[strlen(str)] = -1;
for(i = str_offset; str[i] != ''; i++) {
if(is_digit(str[i])) {
result[i - str_offset] = str[i] - '0';
} else if (is_lower_alphabetic(str[i])) {
result[i - str_offset] = str[i] - 'a' + 10;
} else if (is_upper_alphabetic(str[i])) {
result[i - str_offset] = str[i] - 'A' + 10;
} else {
printf("I don't know how got to this point! ");
}
}
return result;
}
/*
* finds the length of a bignum...
* simply traverses the bignum until a negative number is found.
*/
int bignum_length(int* num) {
int len = 0;
while(num[len] >= 0) { len++; }
return len;
}
/*
* TODO
* Prints out a bignum using digits and lower-case characters
* Current behavior: prints integers
* Expected behavior: prints characters
*/
void bignum_print(int* num) {
int i;
if(num == NULL) { return; }
i = bignum_length(num);
/* print each digit or letter */
for(i = 0; num[i] >= 0; i++) {
char totalBaseValues[] = "0123456789abcdefghijklmnopqrstuvwxyz";
int element = num[i];
printf("%c", totalBaseValues[element]);
}
printf(" ");
}
/*
* Helper for reversing the result that we built backward.
* see add(...) below
*/
void reverse(int* num) {
int i, len = bignum_length(num);
for(i = 0; i < len/2; i++) {
int temp = num[i];
num[i] = num[len-i-1];
num[len-i-1] = temp;
}
}
/*
* addition of input1 and input2
* PROVIDED FOR GUIDANCE
*/
int* add(int* input1, int* input2, int base) {
int len1 = bignum_length(input1);
int len2 = bignum_length(input2);
int resultlength = ((len1 > len2)? len1 : len2) + 2;
int* result = (int*) malloc (sizeof(int) * resultlength);
int r = 0;
int carry = 0;
int sign = input1[len1];
int num1, num2;
len1--;
len2--;
while (len1 >= 0 || len2 >= 0) {
if (len1 >= 0) {
num1 = input1[len1];
} else {
num1 = 0;
}
if (len2 >= 0) {
num2 = input2[len2];
} else {
num2 = 0;
}
result[r] = (num1 + num2 + carry) % base;
carry = (num1 + num2 + carry) / base;
len1--;
len2--;
r++;
}
if (carry > 0) {
result[r] = carry;
r++;
}
result[r] = sign;
reverse(result);
return result;
}
/*
* TODO
* return true if input1 < input2, and false otherwise
*/
bool less_than(int* input1, int* input2) {
int len1 = bignum_length(input1);
int len2 = bignum_length(input2);
// if different lengths we can compare based on lengths
if (len1 != len2) {
return len1 < len2;
} else {
// if the length is the same, then inspect individual elements to compare
for (int i = 0; i < len1; i++) {
if (input1[i] > input2[i]) {
return false;
} else if (input1[i] < input2[i]) {
return true;
}
// if elements are equal, proceed to next indices and check
}
return false; // this means the inputs are equal, therefore false
}
}
/*
* TODO
* return true if input1 > input2, and false otherwise
*/
bool greater_than(int* input1, int* input2) {
int len1 = bignum_length(input1);
int len2 = bignum_length(input2);
// if different lengths we can compare based on lengths
if (len1 != len2) {
return len1 > len2;
} else {
// if the length is the same, then inspect individual elements to compare
for (int i = 0; i < len1; i++) {
if (input1[i] > input2[i]) {
return true;
} else if (input1[i] < input2[i]) {
return false;
}
// if elements are equal, proceed to next indices and check
}
return false; // this means the inputs are equal, therefore false
}
}
/*
* TODO
* return true if input1 == input2, and false otherwise
*/
bool equal_to(int* input1, int* input2) {
int len1 = bignum_length(input1);
int len2 = bignum_length(input2);
// if different lengths we can compare based on lengths
if (len1 != len2) {
return false;
} else {
// if the length is the same, then inspect individual elements to compare
for (int i = 0; i < len1; i++) {
if (input1[i] != input2[i]) {
return false;
}
// if elements are equal, proceed to next indices and check
}
return true; // this means the inputs are equal, therefore false
}
}
/*
* TODO
* multiply input1 * input2
*/
int* multiply(int* input1, int* input2, int base) {
int len1 = bignum_length(input1);
int len2 = bignum_length(input2);
int resultlength = (len1 * len2) + 2;
int num1;
int* result = (int*) malloc (sizeof(int) * resultlength);
for (int i = 0; i < len1; i++) {
num1 = input1[i] * (pow(base, len1 - 1 - i));
for (int j = 0; j < num1; j++) {
result = add(result, input2, base);
}
}
return result;
}
/*
* TODO
* This function is where you will write the code that performs the heavy lifting,
* actually performing the calculations and comparisons on input1 and input2.
* This function prints the result using printf. It does not return any value.
* The text printed should always be of the form
* Result: ...
* Where the ... is either a number of one of 'true' or 'false'.
* See the project write-up for examples.
* HINT: For better code structure, use helper functions.
*/
void perform_operation(int* input1, int* input2, char op, int base) {
if(op == '+') {
int* result = add(input1, input2, base);
printf("Result: ");
bignum_print(result);
free(result);
}
if (op == '*') {
int* result = multiply(input1, input2, base);
printf("Result: ");
bignum_print(result);
free(result);
}
if (op == '>') {
bool result = greater_than(input1, input2);
char* boolName;
// Convert boolean integer to true or false char arrays
if (result == 0) {
boolName = "false";
} else {
boolName = "true";
}
printf("Result: %s", boolName);
printf(" ");
}
if (op == '=') {
bool result = equal_to(input1, input2);
char* boolName;
// Convert boolean integer to true or false char arrays
if (result == 0) {
boolName = "false";
} else {
boolName = "true";
}
printf("Result: %s", boolName);
printf(" ");
}
if (op == '<') {
bool result = less_than(input1, input2);
char* boolName;
// Convert boolean integer to true or false char arrays
if (result == 0) {
boolName = "false";
} else {
boolName = "true";
}
printf("Result: %s", boolName);
printf(" ");
}
}
/*
* Print to "stderr" and exit program
*/
void print_usage(char* name) {
fprintf(stderr, "---------------------------------------------------- ");
fprintf(stderr, "Usage: %s base input1 operation input2 ", name);
fprintf(stderr, "base must be number between 2 and 36, inclusive ");
fprintf(stderr, "input1 and input2 are arbitrary-length integers ");
fprintf(stderr, "Permited operations are allowed '+', '*', '<', '>', and '=' ");
fprintf(stderr, "---------------------------------------------------- ");
exit(1);
}
/*
* MAIN: Run the program and tests your functions.
* sample command: ./bignum 4 12 + 13
* Result: 31
*/
int main(int argc, char** argv) {
int input_base;
int* input1;
int* input2;
if(argc != 5) {
print_usage(argv[0]);
}
input_base = string_to_integer(argv[1]);
if(!valid_base(input_base)) {
fprintf(stderr, "Invalid base: %s ", argv[1]);
print_usage(argv[0]);
}
if(!valid_input(argv[2], input_base)) {
fprintf(stderr, "Invalid input1: %s ", argv[2]);
print_usage(argv[0]);
}
if(!valid_input(argv[4], input_base)) {
fprintf(stderr, "Invalid input2: %s ", argv[4]);
print_usage(argv[0]);
}
char op = argv[3][0];
if(op != '+' && op != '*' && op != '<' && op != '>' && op != '=') {
fprintf(stderr, "Invalid operation: %s ", argv[3]);
print_usage(argv[0]);
}
input1 = string_to_integer_array(argv[2]);
input2 = string_to_integer_array(argv[4]);
perform_operation(input1, input2, op, input_base);
free(input1);
free(input2);
exit(0);
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.