I'm new to C, so I apologize if the answer to this is painfully obvious! I mean to loop through two 2D arrays, passing correspondingly indexed members as arguments to my chineseRemainder routine, i.e. for each iteration, array1[i] and array2[i] should be passed to the routine, where i = i. I am expecting the output of a call to printf to be a certain set of numbers -- instead I am getting all zeros. Here is the main routine, where I call the CR function. **edit I gave xp and xq arbitrary int values, since they do not seem to be the problem, and giving them such values gives the same output.
int main(){
int xp, xq, p = 61, q = 3;
int i, j;
reverseInteger();
for(i = 0; i < 32; ++i){
for(j = 0; j < 10; ++j){
xq = 4;
xp = 1;
printf("%i\n", chineseRemainder(xq, xp, p, q));
}
}
return 0;
}
For troubleshooting's sake, I dumped the contents of xq and xp to make sure those assignments were going through: they are. The problem must be with the CR routine, because it is printing zero even when I pass any set of integers to it. So, here is that function, and its dependencies:
float power(int base, int exp) {
int i;
float result = 1;
if (exp == 0)
result = 1;
else if (exp == 1)
result = base;
else if(exp > 1){
for (i = 0; i < exp; ++i)
result *= base;
}
else
result = 1/power(base, -exp);
return result;
}
float powerMod(int q, int e, int p){
float result;
result = (int)power(q, e) % p;
return result;
}
typedef struct arrayInside{
int array[30][10];
} arrayInside;
arrayInside codesInside;
struct arrayInside reverseInteger(){
int i, j, number;
for(i = 0; i < 30; ++i){
j = 10;
number = (aryConversion(q3[i], 3));
do {
codesInside.array[i][j-1] = number % 10;
--j;
number = number / 10;
}
while (number);
codesInside.array[i][0] = 0;
};
return codesInside;
}
int chineseRemainder(int xq, int xp, int p, int q){
int tp;
int ceiling = (p*q-1)/2;
tp = ((int)(q * (powerMod(q, -1, p))*xp + p * powerMod(p, -1, q) * xq) % (p*q));
if(tp > ceiling)
tp-=p*q;
return tp;
}
Your chineseRemainder actually returns 0 every time. Look at this -
((int)(q * (powerMod(q, -1, p))*xp + p * powerMod(p, -1, q) * xq) % (p*q));
powerMod(q, -1, p) is zero. So multiplying and adding it also going to give zero. Your function actually returns zero. There is nothing wrong. You probably need to check the logic or change the data types.
Related
I have a very large number (>100 digits long) so it can't be stored as an int or even an unsigned long long (aka uint64_t). The array looks like this:
{5, 1, 2 ... 8, 6}
The array must contain single digit ints.
Question
What would be a simple, and most importantly efficient, way of multiplying this 'number' (keeping it as an array) by a single digit?
What I have tried
As I am fairly new to C, this code is not a masterpiece. Far from it.
struct returnpointer { int * pointer; int length; };
returnpointer mul_arrays(int * x, int y, int lengthof_x) {
returnpointer result_end;
int result[lengthof_x * 2 + 1];
int final_result[lengthof_x * 2 + 1];
int carry = 0;
int j = 0;
//multiply 'y' by all digits of x, which creates multidigit ints
//and also reverses the direction of the array (to allow carrying)
for (int i = lengthof_x; i >= 0; i--) {
result[j] = x[i] * y;
j++;
}
int i = 0;
j = lengthof_x
//this is the bit that doesn't work: it attempts to work out the carry
//however after hours of debugging I can't get it to work.
while (carry > 0 || i < lengthof_x + 1) {
if (result[j] > 9) {
carry = result[j] / 10;
final_result[i] = result[j] % 10;
final_result[i + 1] = carry;
} else {
final_result[i] = result[j];
carry = 0;
}
i++;
j--;
}
result_end.pointer = result;
result_end.length = i + 1;
return result_end;
}
This code does not work properly. It is just an illustration of what I have tried (if it worked I would not be posting this).
In addition, it would be nice to know if the approach I am (trying to) use is the most efficient, as the program it will be incorporated into is very time-intensive so the faster the function the less time the entire program will take.
Thanks in advance.
EDIT:
My compiler is g++.
As requested, here is a code example that multiplies an array by a single digit. The array is little-endian. For a simple example, I have assumed that the array is of fixed length, a more complex one would allocate array memory and extend it if the array grows too big.
#include <stdio.h>
#define BIGLEN 20
typedef struct {
int length;
int array[BIGLEN];
} biggy_t;
void bigmul(biggy_t *big, int mul)
{
int carry = 0, partial;
for(int i = 0; i < big->length; i++) {
partial = big->array[i] * mul + carry;
big->array[i] = partial % 10;
carry = partial / 10;
}
if(carry) {
big->array[big->length] = carry;
big->length++;
}
}
void bigout(biggy_t *big)
{
for(int i = big->length-1; i >= 0; i--) {
printf("%d", big->array[i]);
}
}
int main(int argc, char *argv[])
{
biggy_t big = { 6, { 5, 1, 2, 3, 8, 6 }}; // reverse order
bigout(&big);
printf(" * 7 = ");
bigmul(&big, 7);
bigout(&big);
printf("\n");
}
Program output
683215 * 7 = 4782505
I wrote a bignum implementation in which I can chose the radix. 10 or 100 for byte storage, much more for 32-bit storage. Sticking to a power of 10 makes the conversion to decimal output easier than a power of 2 radix, with a small time penalty for not using the full capacity of the storage type.
So a few observations:
1) I don't think there is any need to reverse the array. Just process it from least significant to most significant digit.
2) There is no reason to store temporary values larger than your allowable digit range. Just do the carry as you go, like you would if you were doing it by hand:
carry = 0
for i in all_the_digits:
product = x[i]*y + carry
x[i] = product%10
carry = product/10
3) you can store the digits as uint8_t without fear of overflow - this will make your array 1/4 the current size, which should improve speed due to caching effects.
There are multiple problems in your code. Not sure I have spotted all of them but here is some to start with.
This loop:
for (int i = lengthof_x; i >= 0; i--) {
result[j] = x[i] * y;
j++;
}
execute "lengthof_x + 1" times. In other words - one time too many! You want to change it to:
for (int i = lengthof_x - 1; i >= 0; i--) { // notice the "- 1"
result[j] = x[i] * y;
j++;
}
Further you have:
result_end.pointer = result;
but it seems that you have calculated the result in the variable final_result so you are returning the wrong array.
However - in any case you are not allowed to return a pointer to a local array! It will go out of scope when the function returns. So even if you do:
result_end.pointer = final_result;
it is still invalid code. You'll need to malloc the array (and that will hurt performance).
Then you have:
result_end.length = i + 1;
So you increment the length in all cases. That's wrong. You should only increment when you have a carry.
Below I have tried to fix your code, i.e. I have tried to keep the overall structure of your code so that you can see where you did mistakes.
#include <stdio.h>
#include <stdlib.h>
struct returnpointer { int * pointer; int length; };
void print_num(struct returnpointer * num)
{
printf("len=%d\nvalue=", num->length);
for(int i = 0; i <num->length; i++) {
printf("%d", num->pointer[i]);
}
}
struct returnpointer mul_arrays(int * x, int y, int lengthof_x) {
struct returnpointer result_end;
int result[lengthof_x + 1];
// Multiply all element and revert array
int j = 0;
for (int i = lengthof_x-1; i >= 0; i--) {
result[j] = x[i] * y;
j++;
}
// Handle carry
int carry = 0;
for (j = 0; j < lengthof_x; j++) {
result[j] = result[j] + carry;
carry = result[j] / 10;
result[j] = result[j] % 10;
}
// Did length increase
if (carry)
{
lengthof_x++;
result[j] = carry;
}
// malloc result and revert back to desired format
j = 0;
int* final_result = malloc(lengthof_x * sizeof *final_result);
for (int i = lengthof_x-1; i >= 0; i--) {
final_result[j] = result[i];
j++;
}
result_end.pointer = final_result;
result_end.length = lengthof_x;
return result_end;
}
int main(int argc, char *argv[])
{
int arr[] = { 5, 1, 2, 3, 8, 6};
struct returnpointer num = mul_arrays(arr, 2, 6); // 512386 * 2 -> 1024772
print_num(&num);
}
Output:
len=7
value=1024772
Notice however that this is not an optimal solution...
I'm very new to C, although I've done a decent amount of Java before. I'm making a basic Pascal's Triangle program and I've been looking at it for an hour trying to get it working. All the logic seems correct to me but I'll probably die before I realize what's wrong. Here's the program:
#include <stdio.h>
#include <stdlib.h>
double fact(int num);
int main()
{
int row_index = 0;
printf("Enter the row index : ");
scanf("%d",&row_index);
printf("\n");
int i;
double output1 = 0;
double output2 = 0;
double output3 = 0;
double output4 = 0;
double output5 = 0;
int output6 = 0;
for(i = 0; i <= (row_index + 1); i++)
{
output1 = fact(row_index);
output2 = fact(i);
output3 = row_index - i;
output4 = fact(output3);
output5 = output1 / (output2 * output4);
output6 = (int)(output5);
printf("%i ",output6);
}
return 0;
}
double fact(int num)
{
double result;
int i;
for(i = 1; i <= num; ++i)
{
result = result * i;
}
return result;
}
The compiler is giving me no errors, and each every time I input a number it gives this as output:
Enter the row index : 6
-2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648 -2147483648
In double fact(int num), the variable result should be explicitly initialized. Also, I would suggest you to define both the return value of the function and variable result to int type.
See (Why) is using an uninitialized variable undefined behavior?.
At a glance, there seems to be several issues.
First:
double fact(int num)
{
double result;
int i;
for(i = 1; i <= num; ++i)
{
result = result * i;
}
return result;
}
result is not initialized to anything. Maybe you need to initialize it to 1?
for(i = 0; i <= (row_index + 1); i++)
{
output2 = fact(i);
output3 = row_index - i;
output4 = fact(output3);
output5 = output1 / (output2 * output4);
}
the first time around, i == 0; which means output2 at best will be 0 (assuming its automatically initialized to 0). If output2 == 0, output5 might be undefined. I say might because of double-precision numbers it may actually not be exactly 0.
I am copying a program whose purpose is to generate and bubble sort a list of random numbers. This is the code:
#include <stdio.h>
#define MAX 10
int a;
int rand_seed=10;
int rand()
{
rand_seed = rand_seed * 1103515245 + 12345;
return (unsigned int)(rand_seed / 65536) % 32768;
}
void main()
{
int i,t,x,y;
//fill array
for (i = 0; i < MAX;i++)
{
a = rand();
printf("%d\n",a);
}
/* bubble sort the array */
for (x = 0; x < MAX-1; x++)
for (y = 0; y < MAX -x - 1; y++)
if (a > a[y+1]) {
t = a;
a = a[y+1];
a[y+1] = t;
}
printf("----------------\n");
for( i = 0; i < MAX;i++)
printf("%d\n",a);
}
I know it's offensive to post the whole thing here but I don't know where the problem is.
I believe your compiler already had the offensive line pointed out. In the code
if (a > a[y+1])
you're trying to use a as an array, while it was defined as an int, earlier
int a;
If you want a to be an array, you have to define it as an array, and populate each member using rand() or similar.
I am pretty sure you wanted a to be an array. In that case try this out:
int a[10];
for (i = 0; i < MAX;i++) {
a[i] = rand();
printf("%d\n",a[i]);
}
And also this part would be changed into:
if (a[y] > a[y+1]) {
t = a[y];
a[y] = a[y+1];
a[y+1] = t;
}
I'm working through an algorithms MOOC and have a small program that takes an array A of ints in arbitrary order, counts the number of inversions (an inversion being the number of pairs (i,j) of array indices with i<j and A[i] > A[j]).
Below is the code I've written. I'm trying to tackle it using a "divide and conquer" approach where we recursively split the input array into two halves, sort each half individually while counting the inversions and then merge the two halves.
The trick is I need to keep track of the number of inversions and sort the arrays, so I pass the original array around the various recursive calls as an argument to the function and pass the count of inversions as a return value.
The code executes correctly through the first set of recursive calls that successively divide and sort [1,5,3], however when I get to the 3rd invocation of mergeAndCountSplitInv it crashes at the line:
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
with the error:
malloc: *** error for object 0x100103abc: pointer being realloc'd was not allocated
I can't see where I'm not using malloc correctly and I've combed through this checking to see I'm doing the pointer arithmetic correctly and can't spot any errors, but clearly error(s) exist.
Any help is appreciated.
// main.c
// inversionInC
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// function to help with debugging array/pointer arithmetic
void logArrayLenAndContents (char *arrayName, int arrayToPrint[], int arrayLen){
printf("%s\n", arrayName);
printf("len:%d\n", arrayLen);
for (int idx = 0; idx < arrayLen; idx++) {
printf("array[%d]: %d\n", idx, arrayToPrint[idx]);
}
}
int mergeAndCountSplitInv(int sortedArrayLeft[], int leftLen, int sortedArrayRight[], int rightLen)
{
printf("Calling mergeAndCount with sortedArrayLeft:\n");
logArrayLenAndContents("left Array", sortedArrayLeft, leftLen);
printf("...and sortedArrayRight:\n");
logArrayLenAndContents("right Array", sortedArrayRight, rightLen);
int i = 0;
int j = 0;
int k = 0;
int v = 0; // num of split inversions
int* outArray;
outArray = malloc((leftLen + rightLen) * sizeof(int));
while (i < leftLen && j < rightLen) {
if (sortedArrayLeft[i] < sortedArrayRight[j]) {
outArray[k] = sortedArrayLeft[i];
i++;
} else{
outArray[k] = sortedArrayRight[j];
v += leftLen - i;
j++;
}
k++;
}
// if at the end of either array then append the remaining elements
if (i < leftLen) {
while (i < leftLen) {
outArray[k] = sortedArrayLeft[i];
i++;
k++;
}
}
if (j < rightLen) {
while (j < rightLen) {
outArray[k] = sortedArrayRight[j];
j++;
k++;
}
}
printf("Wrapping up mergeAndCount where outArray contains:\n");
logArrayLenAndContents("outArray", outArray, k);
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
int sortAndCount(int inArray[], int inLen){
printf("Calling sortAndCount with:\n");
logArrayLenAndContents("inArray", inArray, inLen);
if (inLen < 2) {
return 0;
}
int inArrayLenPart1 = ceil(inLen/2.0);
int inArrayLenPart2 = inLen - inArrayLenPart1;
int* rightArray = malloc(sizeof(int) * inArrayLenPart2);
rightArray = &inArray[inArrayLenPart1];
int x = sortAndCount(inArray, inArrayLenPart1);
printf("sortAndCount returned x = %d\n\n", x);
int y = sortAndCount(rightArray, inArrayLenPart2);
printf("sortAndCount returned y = %d\n\n", y);
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
printf("mergeAndCount returned z = %d\n", z);
return x+y+z;
}
int main(int argc, const char * argv[])
{
static int* testArray;
testArray = malloc(5 * sizeof(int));
for (int i = 0; i<=4; i++) {
testArray[0] = 1;
testArray[1] = 5;
testArray[2] = 3;
testArray[3] = 2;
testArray[4] = 4;
}
int x = sortAndCount(testArray, 5);
printf("x = %d\n", x);
return 0;
}
This happens because the value of sortedArrayLeft gets lost as soon as the function returns. The realocated value does not make it to the caller, so inArray of the sortAndCount may be pointing to freed memory if realloc needs to reallocate and copy.
In order to fix this, pass a pointer to the pointer, letting sortedArrayLeft to propagate back to inArray of sortAndCount:
int mergeAndCountSplitInv(int **sortedArrayLeft, int leftLen, int sortedArrayRight[], int rightLen) {
...
*sortedArrayLeft = realloc(*sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
...
int sortAndCount(int **inArray, int inLen) {
...
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
}
...
int x = sortAndCount(&testArray, 5);
So.. I have something like this. It is supposed to create arrays with 10, 20, 50 100 .. up to 5000 random numbers that then sorts with Insertion Sort and prints out how many comparisions and swaps were done .. However, I am getting a runtime exception when I reach 200 numbers large array .. "Access violation writing location 0x00B60000." .. Sometimes I don't even reach 200 and stop right after 10 numbers. I have literally no idea.
long *arrayIn;
int *swap_count = (int*)malloc(sizeof(int)), *compare_count = (int*)malloc(sizeof(int));
compare_count = 0;
swap_count = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
compare_count = 0;
swap_count = 0;
free(arrayIn);
}
}
}
EDIT: ok with this free(arrayIn); I get this " Stack cookie instrumentation code detected a stack-based buffer overrun." and I get nowhere. However without it it's "just" "Access violation writing location 0x00780000." but i get up to 200numbers eventually
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
arr[i] = (RAND_MAX + 1)*rand() + rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
I am sure your compiler told you what was wrong.
You are passing a long** to a function that expects a int* at the line
fill_array(&arrayIn, n);
function prototype is
void fill_array(int *arr, int n)
Same problem with the other function. From there, anything can happen.
Always, ALWAYS heed the warnings your compiler gives you.
MAJOR EDIT
First - yes, the name of an array is already a pointer.
Second - declare a function prototype at the start of your code; then the compiler will throw you helpful messages which will help you catch these
Third - if you want to pass the address of a simple variable to a function, there is no need for a malloc; just use the address of the variable.
Fourth - the rand() function returns an integer between 0 and RAND_MAX. The code
a[i] = (RAND_MAX + 1) * rand() + rand();
is a roundabout way of getting
a[i] = rand();
since (RAND_MAX + 1) will overflow and give you zero... If you actually wanted to be able to get a "really big" random number, you would have to do the following:
1) make sure a is a long * (with the correct prototypes etc)
2) convert the numbers before adding / multiplying:
a[i] = (RAND_MAX + 1L) * rand() + rand();
might do it - or maybe you need to do some more casting to (long); I can never remember my order of precedence so I usually would do
a[i] = ((long)(RAND_MAX) + 1L) * (long)rand() + (long)rand();
to be 100% sure.
Putting these and other lessons together, here is an edited version of your code that compiles and runs (I did have to "invent" a print_array) - I have written comments where the code needed changing to work. The last point above (making long random numbers) was not taken into account in this code yet.
#include <stdio.h>
#include <stdlib.h>
// include prototypes - it helps the compiler flag errors:
void fill_array(int *arr, int n);
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count);
void print_array(int *arr, int n, int *swap_count, int *compare_count);
int main(void) {
// change data type to match function
int *arrayIn;
// instead of mallocing, use a fixed location:
int swap_count, compare_count;
// often a good idea to give your pointers a _p name:
int *swap_count_p = &swap_count;
int *compare_count_p = &compare_count;
// the pointer must not be set to zero: it's the CONTENTs that you set to zero
*compare_count_p = 0;
*swap_count_p = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count_p, compare_count_p);
print_array(arrayIn, n, swap_count_p, compare_count_p);
swap_count = 0;
compare_count = 0;
free(arrayIn);
}
}
}
return 0;
}
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
// arr[i] = (RAND_MAX + 1)*rand() + rand(); // causes integer overflow
arr[i] = rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
void print_array(int *a, int n, int* sw, int *cc) {
int ii;
for(ii = 0; ii < n; ii++) {
if(ii%20 == 0) printf("\n");
printf("%d ", a[ii]);
}
printf("\n\nThis took %d swaps and %d comparisons\n\n", *sw, *cc);
}
You are assigning the literal value 0 to some pointers. You are also mixing "pointers" with "address-of-pointers"; &swap_count gives the address of the pointer, not the address of its value.
First off, no need to malloc here:
int *swap_count = (int*)malloc(sizeof(int)) ..
Just make an integer:
int swap_coint;
Then you don't need to do
swap_coint = 0;
to this pointer (which causes your errors). Doing so on a regular int variable is, of course, just fine.
(With the above fixed, &swap_count ought to work, so don't change that as well.)
As I told in the comments, you are passing the addresses of pointers, which point to an actual value.
With the ampersand prefix (&) you are passing the address of something.
You only use this when you pass a primitive type.
E.g. filling the array by passing an int. But you are passing pointers, so no need to use ampersand.
What's actually happening is that you are looking in the address space of the pointer, not the actual value the pointer points to in the end. This causes various memory conflicts.
Remove all & where you are inputting pointers these lines:
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
So it becomes:
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count, compare_count);
print_array(arrayIn, n, swap_count, compare_count);
I also note that you alloc memory for primitive types, which could be done way simpler:
int compare_count = 0;
int swap_count = 0;
But if you choose to use the last block of code, DO use &swap_count and &compare_count since you are passing primitive types, not pointers!