Question:
I want to know the difference of number n and a, both stored in char
arrays in ALI structures. Basically, what I'm doing is initialising
two integers (temp_n and temp_a) with the current digits of n and a,
subtracting them and placing the result in a new ALI instance named
k. If the j-th digits of a is greater than the i-th digit of n, then
I add 10 to the digit if n, finish the subtraction, and in the next
turn, I increase temp_a by one. The value of number a certainly falls
between 1 and n - 1 (that's given). If a is shorter than n, as soon
as I reach the last digits of a, I put the remaining digits of n to
the result array k. And I do this all backwards, so the initialising
value of i would be the size of n -1.
Example:
I store a number in a structure like this:
typedef struct Arbitrary_Large_Integer
{
char digits[];
} ALI;
Requirements:
I know that it could be easier to use char arrays instead of a
structure with a single member which barely makes sense, but I'm
forced to put structures in my code this time (that's a requirement
for my assignment).
Code:
ALI *subtraction(ALI n, ALI a, int nLength, int aLength)
{
ALI *result;
result = (ALI*)malloc(nLength * sizeof(ALI));
if (result == NULL)
printf("ERROR");
int temp_n, temp_a, difference;
int i = nLength - 1; //iterator for number 'n'
int j = aLength - 1; //iterator for number 'a'
int k = 0; //iterator for number 'k', n - a = k
bool carry = false; //to decide whether a carry is needed or not the turn
for (i; i >= 0; i--)
{
//subtracting 48 from n.digits[i], so temp_n gets the actual number
//and not its ASCII code when the value is passed
temp_n = n.digits[i] - ASCIICONVERT;
temp_a = a.digits[j] - ASCIICONVERT;
//Performing subtraction the same way as it's used on paper
if (carry) //if there is carry, a needs to be increased by one
{
temp_a++;
carry = false;
}
if (temp_n >= temp_a)
{
difference = temp_n - temp_a;
}
//I wrote else if instead of else so I can clearly see the condition
else if (temp_a > temp_n)
{
temp_n += 10;
difference = temp_n - temp_a;
carry = true;
}
//placing the difference in array k, but first converting it back to ASCII
result->digits[k] = difference + ASCIICONVERT;
k++;
//n is certainly longer than a, so after every subtraction is performed on a's digits,
//I place the remaining digits of n in k
if (j == 0)
{
for (int l = i - 1; l >= 0; l--)
{
result->digits[k] = n.digits[l];
k++;
}
//don't forget to close the array
result->digits[k] = '\0';
break;
}
j--;
}
//reverse the result array
_strrev(result->digits);
return result;
}
Output/Error:
Output results
It seems like when the array is passed to the function, its value
changes for some reason. I can't figure out what's wrong with it.
Problems:
Non-standard C
The typedef is not a valid standard C structure. The Flexible Array Member(FAM) .digits must be accompanied by at least one more prior named member in addition to the flexible array member. Recommend to put .nLength as the first member.
// Not standard
typedef struct Arbitrary_Large_Integer {
char digits[];
} ALI;
malloc(0)??
Since code is using a non-standard C, watch out that nLength * sizeof(ALI) may be the same as nLength * 0.
No room for the null character
Code is attempting to use .digits as a string with _strrev(), themallloc() is too small by 1, at least.
Other problems may exist
A Minimal, Complete, and Verifiable example is useful for additional fixes/solutions
Related
I have got an assignment and i'll be glad if you can help me with one question
in this assignment, i have a question that goes like this:
write a function that receives an array and it's length.
the purpose of the function is to check if the array has all numbers from 0 to length-1, if it does the function will return 1 or 0 otherwise.The function can go through the array only one.
you cant sort the array or use a counting array in the function
i wrote the function that calculate the sum and the product of the array's values and indexes
int All_Num_Check(int *arr, int n)
{
int i, index_sum = 0, arr_sum = 0, index_multi = 1, arr_multi = 1;
for (i = 0; i < n; i++)
{
if (i != 0)
index_multi *= i;
if (arr[i] != 0)
arr_multi *= arr[i];
index_sum += i;
arr_sum += arr[i];
}
if ((index_sum == arr_sum) && (index_multi == arr_multi))
return 1;
return 0;
}
i.e: length = 5, arr={0,3,4,2,1} - that's a proper array
length = 5 , arr={0,3,3,4,2} - that's not proper array
unfortunately, this function doesnt work properly in all different cases of number variations.
i.e: length = 5 , {1,2,2,2,3}
thank you your help.
Checking the sum and product is not enough, as your counter-example demonstrates.
A simple solution would be to just sort the array and then check that at every position i, a[i] == i.
Edit: The original question was edited such that sorting is also prohibited. Assuming all the numbers are positive, the following solution "marks" numbers in the required range by negating the corresponding index.
If any array cell already contains a marked number, it means we have a duplicate.
int All_Num_Check(int *arr, int n) {
int i, j;
for (i = 0; i < n; i++) {
j = abs(arr[i]);
if ((j >= n) || (arr[j] < 0)) return 0;
arr[j] = -arr[j];
}
return 1;
}
I thought for a while, and then i realized that it is a highly contrained problem.
Things that are not allowed:
Use of counting array.
Use of sorting.
Use of more than one pass to the original array.
Hence, i came up with this approach of using XOR operation to determine the results.
a ^ a = 0
a^b^c = a^c^b.
Try this:
int main(int argc, char const *argv[])
{
int arr[5], i, n , temp = 0;
for(i=0;i<n; i++){
if( i == 0){
temp = arr[i]^i;
}
else{
temp = temp^(i^arr[i]);
}
}
if(temp == 0){
return 1;
}
else{
return 0;
}
}
To satisfy the condition mentioned in the problem, every number has to occour excatly once.
Now, as the number lies in the range [0,.. n-1], the looping variable will also have the same possible range.
Variable temp , is originally set to 0.
Now, if all the numbers appear in this way, then each number will appear excatly twice.
And XORing the same number twice results in 0.
So, if in the end, when the whole array is traversed and a zero is obtained, this means that the array contains all the numbers excatly once.
Otherwise, multiple copies of a number is present, hence, this won't evaluate to 0.
This is the code:
char binarySearch(unsigned int target, int* primes, unsigned int size){
int* ptrToArray = primes;
unsigned int first = 0;
unsigned int last = size;
while (first <= last){
unsigned int middle = first + (last - first) / 2;
printf("first: %d, last: %d, middle: %d\n", first, last , middle);
if (ptrToArray[middle] == target){
return 1;
}
if (ptrToArray[middle] < target){
first = middle + 1;
}else{
last = middle - 1;
}
}
return 0;
}
This is the output:
I've been staring at that peace of code for more than one should and still can't figure out where is the flaw.
If middle is 0, as near the end of your debug output, the statement
last = middle - 1
causes an integer overflow; the conditions have to be reworked a bit.
You may get an out of bound when you are looking for an element not in the array, and is bigger than the array, due to allowing keep iteration when last and first equal each other in while (first <= last)
Think of what happens when you send an empty array: size == 0:
first = 0, last = 0, and thus: (first <= last) == true.
Then, middle = 0 + (0 - 0)/2 = 0, and next you access ptrToArray[0], which is out of bound.
The problem is that you define your index variables (first, last, middle) as unsigned int while in your logic, last can in fact become negative. However, in that case, since they're defined as unsigned and because of the way 2's complement representation of negative numbers works, the condition in your while loop is still true.
Take a look at the following example code for illustration:
#include <stdio.h>
int main() {
/* defining the variables as unsigned */
unsigned int first_u = 0;
unsigned int last_u = -1;
if (first_u <= last_u)
printf("less than\n");
else
printf("greater or equal\n");
/* defining the variables as signed */
int first_s = 0;
int last_s = -1;
if (first_s <= last_s)
printf("less than\n");
else
printf("greater or equal\n");
return 0;
}
Other than that, you should use either < in your while-condition or define the initial value of last as size-1. Otherwise, if you're searching for an element that is greater than the last element in your array, you will run out of bounds.
Firstly the negative value of middle is due to overflow (unsigned int).
Also I think you should have : unsigned int last = size-1 because if first becomes equal to last=size the you will use ptrToArray[middle] and middle=size so it will be out of array bounds. This will solve also the case of size =0 mentioned above .
Finally to make your code more easy to read you could write :
middle =(first+last)/2 which is the middle of [first,last] space, and equals to first+(last-first)/2 .
I'm trying to write a C program which performs multiplication of two numbers without directly using the multiplication operator, and it should take into account numbers which are sufficiently large so that even the usual addition of these two numbers cannot be performed by direct addition.
I was motivated for this when I was trying to (and successfully did) write a C program which performs addition using character strings, I did the following:
#include<stdio.h>
#define N 100000
#include<string.h>
void pushelts(char X[], int n){
int i, j;
for (j = 0; j < n; j++){
for (i = strlen(X); i >= 0; i--){
X[i + 1] = X[i];
}
X[0] = '0';
}
}
int max(int a, int b){
if (a > b){ return a; }
return b;
}
void main(){
char E[N], F[N]; int C[N]; int i, j, a, b, c, d = 0, e;
printf("Enter the first number: ");
gets_s(E);
printf("\nEnter the second number: ");
gets_s(F);
a = strlen(E); b = strlen(F); c = max(a, b);
pushelts(E, c - a); pushelts(F, c - b);
for (i = c - 1; i >= 0; i--){
e = d + E[i] + F[i] - 2*'0';
C[i] = e % 10; d = e / 10;
}
printf("\nThe answer is: ");
for (i = 0; i < c; i++){
printf("%d", C[i]);
}
getchar();
}
It can add any two numbers with "N" digits. Now, how would I use this to perform multiplication of large numbers? First, I wrote a function which performs the multiplication of number, which is to be entered as a string of characters, by a digit n (i.e. 0 <= n <= 9). It's easy to see how such a function is written; I'll call it (*). Now the main purpose is to multiply two numbers (entered as a string of characters) with each other. We might look at the second number with k digits (assuming it's a1a2.....ak) as:
a1a2...ak = a1 x 10^(k - 1) + a2 x 10^(k - 2) + ... + ak-1 x 10 + ak
So the multiplication of the two numbers can be achieved using the solution designed for addition and the function (*).
If the first number is x1x2.....xn and the second one is y1y2....yk, then:
x1x2...xn x y1y2...yk = (x1x2...xn) x y1 x 10^(k-1) + .....
Now the function (*) can multiply (x1x2...xn) with y1 and the multiplication by 10^(k-1) is just adding k-1 zero's next to the number; finally we add all of these k terms with each other to obtain the result. But the difficulty lies in just knowing how many digits each number contains in order to perform the addition each time inside the loop designed for adding them together. I have thought about doing a null array and each time adding to it the obtained result from multiplication of (x1x2....xn) by yi x 10^(i-1), but like I've said I am incapable of precising the required bounds and I don't know how many zeros I should each time add in front of each obtained result in order to add it using the above algorithm to the null array. More difficulty arises when I'll have to do several conversions from char types into int types and conversely. Maybe I'm making this more complicated than it should; I don't know if there's an easier way to do this or if there are tools I'm unaware of. I'm a beginner at programming and I don't know further than the elementary tools.
Does anyone have a solution or an idea or an algorithm to present? Thanks.
There is an algorithm for this which I developed when doing Small Factorials problem on SPOJ.
This algorithm is based on the elementary school multiplication method. In school days we learn multiplication of two numbers by multiplying each digit of the first number with the last digit of the second number. Then multiplying each digit of the first number with second last digit of the second number and so on as follows:
1234
x 56
------------
7404
+6170- // - is denoting the left shift
------------
69104
What actually is happening:
num1 = 1234, num2 = 56, left_shift = 0;
char_array[] = all digits in num1
result_array[]
while(num2)
n = num2%10
num2 /= 10
carry = 0, i = left_shift, j = 0
while(char_array[j])
i. partial_result = char_array[j]*n + carry
ii. partial_result += result_array[i]
iii. result_array[i++] = partial_result%10
iv. carry = partial_result/10
left_shift++
Print the result_array in reverse order.
You should note that the above algorithm work if num1 and num2 do not exceed the range of its data type. If you want more generic program, then you have to read both numbers in char arrays. Logic will be the same. Declare num1 and num2 as char array. See the implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char num1[200], num2[200];
char result_arr[400] = {'\0'};
int left_shift = 0;
fgets(num1, 200, stdin);
fgets(num2, 200, stdin);
size_t n1 = strlen(num1);
size_t n2 = strlen(num2);
for(size_t i = n2-2; i >= 0; i--)
{
int carry = 0, k = left_shift;
for(size_t j = n1-2; j >= 0; j--)
{
int partial_result = (num1[j] - '0')*(num2[i] - '0') + carry;
if(result_arr[k])
partial_result += result_arr[k] - '0';
result_arr[k++] = partial_result%10 + '0';
carry = partial_result/10;
}
if(carry > 0)
result_arr[k] = carry +'0';
left_shift++;
}
//printf("%s\n", result_arr);
size_t len = strlen(result_arr);
for(size_t i = len-1; i >= 0; i-- )
printf("%c", result_arr[i]);
printf("\n");
}
This is not a standard algorithm but I hope this will help.
Bignum arithmetic is hard to implement efficiently. The algorithms are quite hard to understand (and efficient algorithms are better than the naive one you are trying to implement), and you could find several books on them.
I would suggest using an existing Bignum library like GMPLib or use some language providing bignums natively (e.g. Common Lisp with SBCL)
You could re-use your character-string-addition code as follows (using user300234's example of 384 x 56):
Set result="0" /* using your character-string representation */
repeat:
Set N = ones_digit_of_multiplier /* 6 in this case */
for (i = 0; i < N; ++i)
result += multiplicand /* using your addition algorithm */
Append "0" to multiplicand /* multiply it by 10 --> 3840 */
Chop off the bottom digit of multiplier /* divide it by 10 --> 5 */
Repeat if multiplier != 0.
I'm writing a program to look for the longest Collatz sequence starting under 1,000,000.
I was really proud of this code, it seemed so efficient and clean and well written... until I tried to run it. After a little debugging to get it to compile, I found that when I run the program, it crashes.
I have used both
int array[1000000];
and
int *array;
array = (int*)calloc(s, sizeof(int));
(where s=1000000)
to declare an array of 1,000,000 spaces.
So part A) of my question: Is it ridiculous or possible to declare an array of that size?
and part B) of my question: This is used for a 'checklist' of sorts, checking which numbers have already been seen. Is there a simpler or better or just different method of 'checking off' numbers that I should be using instead?
the code is as follows:
// This is a program to find the longest Collatz sequence starting under 1,000,000
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Collatz sequence: IF EVEN n/2 :: IF ODD 3n+1
//define ints
int i;
int n;
int c; // counter of sequence length
int longestsequence = 0;
int beststart;
int s = 1000000; //size of array
//define int array
//int array[999999];
//define array using calloc
//define pointer for calloc int array
int *array;
// do your calloc thing
array = (int*)calloc(s, sizeof(int)); // allocates 1,000,000 spots (s) of size "int" to array "array"
//fill array
for(i = 0; i < 1000000; i++)
{
array[i] = i;
}
for(i = 999999; i > 500000; i--)
{
if(array[i] == 0) // skip if number has already been seen
goto done;
n = i;
c = 0;
//TEST
printf("Current starting number is: %d\n", i);
//TEST
while(n != 4) // run and count collatz sequence
{
//TEST
//printf("test1\n");
//TEST
if(n % 2 == 0) // EVEN
n = n/2;
else // ODD
n = 3 * n + 1;
//TEST
//printf("test2\n");
//TEST
c++;
//TEST
//printf("test3\n");
//TEST
if(n < 1000000 && array[n] != 0) // makes note of used numbers under 1000000
array[n] = 0;
//TEST
//printf("test4\n");
//TEST
}
if(longestsequence < c)
{
longestsequence = c;
beststart = i;
//TEST
printf("Current best start is: %d\n", beststart);
//TEST
}
done:
}
printf("the starting number that produces the longest Collatz sequence is...\n");
printf("%d\n", beststart);
getchar();
return 0;
}
Thanks for any and all help and suggestions! Links to helpful sources are always appreciated.
UPDATE!
1.My code now looks like this^^^^
and
2.The program runs, and then mysteriously stops at i value 999167
for(i = 999999; i > 4; i++)
You easily go beyond array boundary here. I guess what you meant was
for(i = 999999; i > 4; --i)
// ^^^
Also, as in your implementation, 1 million element is not enough.
Take n == 999999 as example. In the 1st step, you compute 3 * n + 1, which is obviously way larger than 1000000. A simple solution would be change
if(array[n-1] != 0) // makes note of used numbers
array[n-1] = 0;
into
if(n < s && array[n-1] != 0) // makes note of used numbers
array[n-1] = 0;
which just disables result lookup when n is over array boundary.
You could use a simple linked list of numbers, which will reduce the memory requirements at the expense of "long" search times. I've always noticed a bit of repetition:
1
2 → 1 (already seen in 1, so link to the existing 1)
3 → 5 → 16 → 8 → 4 → 2 (already seen in 2, so link to the existing 2)
4 (link to existing after 8)
5 (link to existing after 5)
etc.
You would have a number A and possibly one more number B link to a number N for some numbers, but N would only link to one number C. For example:
A -> N -> C
3 -> 10 -> 5
20 -> 10 -> 5
B -> N -> C
Of course, you could optimize it by storing a length of the list and an extra pointer containing the next adjacent number, allowing you to implement a binary search using that length as a guide.
However, if you're only looking for the longest sequence length instead of the sequence itself, why aren't you merely storing the longest length found and comparing it to the length of the current sequence? Storing the numbers only for calculating the length seems like overkill. Something like the following pseudocode:
Longest := 0
For N = 1 To 1000000
Length := 1
X := N
While X != 1
Length := Length + 1
If IsEven(X) Then
X := 3 * X + 1
Else
X := X / 2
End If
End While
If Length > Longest Then
Longest := Length
End If
End For
Print("Longest sequence less than 1000000 is: ", Longest)
The line
n = 3 * n + 1;
ends up setting the value of n to be higher than the valid index. The highest valid index is 999999. You have to make sure that n is less than or equal to 1000000 before you access the array in:
if(array[n-1] != 0) // makes note of used numbers
array[n-1] = 0;
You don't check the array index [n-1] within the while loop to ensure it doesn't exceed the array bounds of 1,000,000. For example, in your first loop i = 999,999 which makes `n = 999999*3+1 = 2,999,998'.
Solution is to make sure n doesn't exceed your array size.
I basically want to convert a given int number and store individual digits in an array for further processing.
I know I can use % and get each digit and store it. But the thing is if I do not know the number of digits of the int till runtime and hence I cannot allocate the size of the array. So, I cannot work backwards (from the units place).
I also do not want to first store the number backwords in an array and then again reverse the array.
Is there any other way of getting about doing this?
Eg: int num = 12345;
OUTPUT: ar[0] = 1, ar[1] = 2 and so on, where ar[] is an int array.
Convert is probably not the right word. You can take the int, dynamically allocate a new int[], and then store the digits of the int into the int[]. I'm using log base 10 to calculate how many digits num has. Include math.h to use it. The following code is untested, but will give you an idea of what to do.
int num = 12345;
int size = (int)(log10(num)+1);
// allocate array
int *digits = (int*)malloc(sizeof(int) * size);
// get digits
for(int i=size-1; i>=0; --i) {
digits[i] = num%10;
num=num/10; // integer division
}
The easiest way is to calculate number of digits to know the size of an array you need
int input = <input number>; // >= 0
int d, numdigits = 1;
int *arr;
d = input;
while (d /= 10)
numdigits++;
arr = malloc(sizeof(int) * numdigits);
There's even easier way: probably you pass a number to your program as an argument from command line. In this case you receive it as a string in argp[N], so you can just call strlen(argp[N]) to determine number of digits in your number.
If you have a 32-bit integer type, the maximum value will be comprised of 10 digits at the most (excluding the sign for negative numbers). That could be your upper limit.
If you need to dynamically determine the minimum sufficient size, you can determine that with normal comparisons (since calling a logarithmic function is probably more expensive, but a possibility):
size = 10;
if (myint < 1000000000) size--;
if (myint < 100000000) size--;
/* ... */
Declaring the array to be of a dynamic size depends on the C language standard you are using. In C89 dynamic array sizes (based on values calculated during run-time) is not possible. You may need to use dynamically allocated memory.
HTH,
Johan
The following complete program shows one way to do this. It uses unsigned integers so as to not have to worry about converting - you didn't state what should happen for negative numbers so, like any good consultant, I made the problem disappear for my own convenience :-)
It basically works out the required size of an array and allocates it. The array itself has one element at the start specifying how many elements are in the array (a length int).
Each subsequent element is a digit in sequence. The main code below shows how to process it.
If it can't create the array, it'll just give you back NULL - you should also remember to free the memory passed back once you're done with it.
#include <stdio.h>
#include <stdlib.h>
int *convert (unsigned int num) {
unsigned int *ptr;
unsigned int digits = 0;
unsigned int temp = num;
// Figure out how many digits in the number.
if (temp == 0) {
digits = 1;
} else {
while (temp > 0) {
temp /= 10;
digits++;
}
}
// Allocate enough memory for length and digits.
ptr = malloc ((digits + 1) * sizeof (unsigned int));
// Populate array if we got one.
if (ptr != NULL) {
ptr[0] = digits;
for (temp = 0; temp < digits; temp++) {
ptr[digits - temp] = num % 10;
num /= 10;
}
}
return ptr;
}
That convert function above is the "meat" - it allocates an integer array to place the length (index 0) and digits (indexes 1 through N where N is the number of digits). The following was the test program I used.
int main (void) {
int i;
unsigned int num = 12345;
unsigned int *arr = convert (num);
if (arr == NULL) {
printf ("No memory\n");
} else {
// Length is index 0, rest are digits.
for (i = 1; i <= arr[0]; i++)
printf ("arr[%d] = %u\n", i, arr[i]);
free (arr);
}
return 0;
}
The output of this is:
arr[1] = 1
arr[2] = 2
arr[3] = 3
arr[4] = 4
arr[5] = 5
You can find out the number of digits by taking the base-10 logarithm and adding one. For that, you could use the log10 or log10f functions from the standard math library. This may be a bit slower, but it's probably the most exact as long as double has enough bits to exactly represent your number:
int numdigits = 1 + log10(num);
Alternatively, you could repeatedly divide by ten until the result is zero and count the digits that way.
Still another option is just to allocate enough room for the maximum number of digits the type can have. For a 32-bit integer, that'd be 10; for 64-bit, 20 should be enough. You can just zero the extra digits. Since that's not a lot of wasted space even in the worst case, it might be the simplest and fastest option. You'd have to know how many bits are in an int in your setup, though.
You can also estimate fairly well by allocating 3 digits for each 10 bits used, plus one. That should be enough digits unless the number of bits is ridiculously large (way above the number of digits any of the usual int types could have).
int numdigits = 1
unsigned int n = num;
for (n = num; n & 0x03ff; n >>= 10)
numdigits += 3;
/* numdigits is at least the needed number of digits, maybe up to 3 more */
This last one won't work (directly) if the number is negative.
What you basically want to do is to transform your integer to an array of its decimal positions. The printf family of functions perfectly knows how to do this, no need to reinvent the wheel. I am changing the assignment a bit since you didn't say anything about signs, and it simply makes more sense for unsigned values.
unsigned* res = 0;
size_t len = 0;
{
/* temporary array, large enough to hold the representation of any unsigned */
char positions[20] = { 0 };
sprintf(position, "%u", number);
len = strlen(position);
res = malloc(sizeof(unsigned[len]));
for (size_t i = 0; i < len; ++i)
res[i] = position[i] - '0';
}