make two big number add by array in c code - c

I want to construct two big number by array in c programming and make them add.
The following is my code:
void add(unsigned char* a, unsigned char* b, unsigned int len)
{
int i;
unsigned short T;
unsigned char carry = 0;
for (i = len - 1; i >= 0; --i)
{
T = (unsigned short)(a[i]) + (unsigned short)(b[i]) + (unsigned short)carry;
//T = a[i] + b[i] + carry;
if (T > 0xFF)
carry = 1;
else
carry = 0;
a[i] = (unsigned char)T;
}
}
The max value in array a and b for every element is 255.
EDIT1: The highest carry is discarded. The result is save in array a.
EDIT2: replace "Byte" with "carry".
The original code is :
Integer B1(B, SM3_BLOCK_SIZE);
++B1;
for (i = 0; i < ILen; i += v)
(Integer(I + i, v) + B1).Encode(I + i, v);
I write two new function. One is as the Above add(), The other is as following:
void add_one(unsigned char *arr, unsigned int len)
{
int i;
for (i = len-1; i >= 0; --i)
{
arr[len] += 1;
if (arr[len] != 0)
return;
}
}
If my code is rigth, the original code is as following:
add_one(B, SM3_BLOCK_SIZE);
for (i = 0; i < ILen; i += v)
add(I + i, B, SM3_BLOCK_SIZE);

There is (at least) one bug. Look at this code:
void add_one(unsigned char *arr, unsigned int len)
{
int i;
for (i = len-1; i >= 0; --i)
{
arr[len] += 1; // Indexing using len is wrong
if (arr[len] != 0) // Indexing using len is wrong
return;
}
}
You probably want to use i as index.

I assumed you know that you are implementing the add function for a bigendian positive integer.
Avoid using for (i = len-1; i >= 0; --i). You can catch a runtime error when i is unsigned and len is 0. Instead, use for (i = len; i-- > 0;).
If you need a little-endian integer than use for (int i = 0; i < len; ++i)
char add(unsigned char* a, unsigned char* b, unsigned int len)
{
unsigned short carry = 0;
//for (int i = 0; i < len; ++i) // for little-endian
for (int i = len; i-- > 0;) // for big-endian
{
carry += a[i] + b[i];
a[i] = carry & 0xFF;
carry >>= 8;
}
return carry;
}
Tests
unsigned char a[5] = {255,2,3,4,5};
unsigned char b[5] = {255,256-2,256-3,4,5};
char overflow = add(a,b,5);
printf("%d %d %d %d %d / %d",a[0],a[1],a[2],a[3],a[4] , overflow);
Output
255 1 0 8 10 / 1

Related

second smallest element in an array

as a part of a C program I wrote the following function, which finds the second smallest element of an array
unsigned int array_second_min (unsigned int w[], unsigned int n)
{
unsigned int i, erst = UINT_MAX, zweit = UINT_MAX, count = 0;
if (n < 2)
return UINT_MAX;
for (i = 0;i < n; i++) {
if (w[i] == w[i + 1])
count++;
}
if (count == n - 1)
return UINT_MAX;
for (i = 0;i < n;i++) {
if (w[i] < erst)
erst = w[i];
}
for (i = 0;i < n;i++) {
if (w[i] == erst)
continue;
if ((w[i] - erst) < zweit)
zweit = w[i];
}
return zweit;
}
the problem is that it is not really functioning as it should. I think the problem is in the last for loop, but am not sure about that.
Thank you for your help
picture of the output:
The following code will return the second smallest element
unsigned int array_second_min (unsigned int w[], unsigned int n){
unsigned int i, first = UINT_MAX, second = UINT_MAX;
if(n < 2)
return UINT_MAX;
sort(w, w+n);
second = w[n-2];
return second;
}
This is a somewhat more efficient solution, as it is O(n):
struct pair {
int r[2];
};
struct pair small2(int *a, int n) {
int r[2];
int order;
r[0] = a[0];
r[1] = a[1];
order = (r[0] >= r[1]);
for (int i = 2; i < n; i++) {
if (a[i] <= r[order]) {
r[!order] = a[i];
order = !order;
} else if (a[i] <= r[!order]) {
r[!order] = a[i];
}
}
struct pair x;
x.r[0] = r[order];
x.r[1] = r[!order];
return x;
}
There is a lack of detail about duplicates, this handles them in an unsurprising fashion. Note the trickiness of the order variable; this works because you are only interested in the least two, if you wanted the least 3, you would have to add the extra tests. It would remain O(n), but the C would be greater.

Radix Sort Float

I am trying to sort floats with radix. My current algorithm works with unsigned. For example, if I enter values 12, 100, 1 my sorted values are 1, 12, and 100. However, when I use a function to convert floats to ints back to floats after calling the radix sort, my values remain unsorted. They print as they were entered by the user.
I am unsure how to modify my current function to be able to sort floats with radix.
void rs(unsigned int *a, int c) {
int i;
int m = a[0];
int bt = 0;
unsigned int *b = malloc(0 * sizeof(int));
for (i = 0; i < c; i++) {
if (a[i] > m)
m = a[i];
}
while((m>>bt) > 0){
int buck[2] = { 0 };
for (i = 0; i < c; i++) {
buck[(a[i]>>bt)&1]++;
}
for (i = 1; i < 2; i++) {
buck[i] += buck[i-1];
}
for (i = c-1; i >= 0; i--) {
b[--buck[(a[i]>>bt)&1]] = a[i];
}
for (i = 0; i < c; i++) {
a[i] = b[i];
}
bt++;
}
free(b);
}
The function I am using to transform floats to ints to floats is: Radix Sort for Floats
void rfloat(float* arr, size_t size) {
assert(sizeof(unsigned) == sizeof(float) && sizeof(float) == 4);
unsigned* d = malloc(size * sizeof(unsigned));
for (size_t i = 0; i < size; i++) {
// Interpret float as 32-bit unsigned.
d[i] = *(unsigned*) &(arr[i]);
// Flip all except top if top bit is set.
d[i] ^= (((unsigned) (((int) d[i]) >> 31)) >> 1);
// Flip top bit.
d[i] ^= (1u << 31);
}
rs(d, size);
// Inverse transform.
for (size_t i = 0; i < size; i++) {
d[i] ^= (1u << 31);
d[i] ^= (((unsigned) (((int) d[i]) >> 31)) >> 1);
arr[i] = *(float*) &(d[i]);
}
free(d);
}
There's multiple issues.
You use int all over the place where you should be using unsigned (for values) or size_t (for sizes/indices).
You allocate 0 bytes.
(m >> bt) > 0 doesn't work as a stop condition, shifting bits equal or greater than the width is not specified.
After transforming the data types to unsigned the loop boundaries don't work anymore.
I took the liberty of fixing the above and choosing some better variable names:
#include <limits.h>
void rs(unsigned int *a, size_t c) {
size_t i;
unsigned bit = 0;
unsigned *b = malloc(c * sizeof(unsigned));
unsigned m = a[0]; // Max element.
for (i = 0; i < c; i++) {
if (a[i] > m) m = a[i];
}
while (bit < CHAR_BIT*sizeof(m) && (m >> bit)) {
size_t bucket_len[2] = { 0, 0 };
for (i = 0; i < c; i++) bucket_len[(a[i] >> bit) & 1]++;
size_t bucket_end[2] = {bucket_len[0], bucket_len[0] + bucket_len[1]};
for (i = c; i-- > 0; ) {
size_t j = --bucket_end[(a[i] >> bit) & 1];
b[j] = a[i];
}
for (i = 0; i < c; i++) a[i] = b[i];
bit++;
}
free(b);
}

How to concatenate bit by bit in c?

I have matrix of '1' and '0' with the dimensions 8x8. I need to store the whole matrix in one unsigned long long variable bit by bit. How can i do that?
For example, let's take the matrix of '1' and '0' that is 2x2:
The matrix 2x2:
1 0
0 1
The variable must contain: 1001 in bits.
The same example, but over the matrix 8x8 and unsigned long long variable.
That's what i've tried to do:
#include <stdio.h>
int main()
{
unsigned long long result = 0;
char matrix[8][8]; // lets that the matrix is already filled by '1' and '0'
for (i=0; i<SIZE; i++)
{
for (j=0; j<SIZE; j++)
{
result = result | ((unsigned long long)(matrix[i][j] - '0'));
result <<= 1;
}
}
return 0;
}
Is it right? I implemented this nested loop in my algorithm and that didn't work properly.
Converting the text representation of an integer into its integer value can be done using strtoull().
char buf[sizeof(matrix)+1];
memcpy(buf, matrix, sizeof(matrix));
buf[sizeof(matrix)] = '\0';
result = strtoull(buf, NULL, 2);
try this
const int mx_size = 8;
int main() {
unsigned long long result = 0;
bool matrix[8][8]; // lets that the matrix is already filled by '1' and '0'
for (int i =0; i < mx_size; ++i)
matrix[i][i] = 1;
for (int i = 0; i < mx_size; i++) {
for (int j = 0; j < mx_size; j++) {
result |= (unsigned long long)matrix[i][j] << (i*mx_size + j);
}
}
return 0;
}
Here you have the code (a bit more
#include <stdio.h>
#include <stdint.h>
uint64_t convert(char matrix[8][8], int order, char zero)
{
uint8_t byte;
uint64_t result = 0;
for(size_t row = 0; row < 8; row++)
{
byte = 0;
for(size_t column = 0; column < 8; column++)
{
byte <<= 1;
byte |= matrix[row][column] != zero ? 1 : 0; //anything != defined zero char is 1
}
if (order)
{
result |= (uint64_t)byte << (8 * row);
}
else
{
result |= (uint64_t)byte << (56 - 8 * row);
}
}
return result;
}
int main(void) {
char matrix[8][8] =
{
{'1','0','1','0','1','0','1','0'},
{'0','1','0','1','0','1','0','1'},
{'1','1','1','0','0','0','1','1'},
{'0','0','0','1','1','1','0','0'},
{'1','1','1','1','1','0','0','0'},
{'0','0','0','0','1','1','1','1'},
{'1','1','0','0','1','1','0','0'},
{'0','0','1','1','0','0','1','1'},
};
unsigned long long result = convert(matrix, 0, '0');
for(size_t index = 0; index < 64; index ++)
printf("%1d", !!(result & (1ULL << index)));
printf("\n");
result = convert(matrix,1, '0');
for(size_t index = 0; index < 64; index ++)
printf("%1d", !!(result & (1ULL << index)));
printf("\n");
return 0;
}

Why isnt my program returning the correct result for Rabin-Karp substring searching algorithm?

I have to implement the Rabin-Karp string searching algorithm.
I think there is something wrong with my rkhash_next function. My professor told us to compute the next hash value in the string using this equation:
yi+1 = 256^m-1*Y[i+1] + 256^m-2*Y[i+2] + ... + Y[i+m]
= 256 * ( 256^m-2*Y[i+1] + ... Y[i+m-1]) + Y[i+m]
= 256 * ((256^m-1*Y[i] + 256^m-2*Y[i+1] + ... Y[i+m-1]) - 256^m-1*Y[i]) + Y[i+m]
= 256 * ( yi - 256^m-1 * Y[i]) + Y[i+m]
= 256 * yi - 256^m * Y[i] + Y[i+m]
I did this, but my program keeps giving me surprising hash values as it "rolls" through the string. Here is my general code for my rkhash_substring_match:
int rk_substring_match(const char *pattern, const char *doc, int *first_match_ind)
{
int plength = strlen(pattern);
int dlength = strlen(doc);
int i,j,x;
int counter = 0;
int first_match = 0;
first_match_ind = &first_match;
long long hash = 256;
long long *h;
long long phash = 0;
long long dhash = 0;
for (x = 0; x <= plength-1; x++)
hash *= 256;
phash = rkhash_init(pattern, plength,h);
dhash = rkhash_init(doc, plength,h);
for(i = 0; i <= dlength - plength; i++) {
if (phash == dhash) {
for (j = 0; j < plength; j++)
if (doc[i+j] != pattern[j])
break;
if (j == plength && counter == 0)
first_match = i;
if (j == plength)
counter++;
}
printf("%lld\n", dhash);
dhash = rkhash_next(dhash,hash,doc[i + 1], doc[i+plength]);
}
return counter;
}
In my class, long long variables are used to store hash values and 256^m for later usage in the program. Below is rkhash_init which generates the hash value and stores 256^m in the value of h:
long long rkhash_init(const char *charbuf, int m, long long *h)
{
int i,j;
long long value = 1;
long long hash = 0;
for (j = 0; j < m; j++)
value *= 256;
h = &value;
long long val = value;
for (i = 0; i < m -1 ; i++) {
value = value/256;
hash += mmul(value, charbuf[i]);
}
hash += charbuf[m-1];
return hash;
}
And here is the problem child, rkhash_next:
long long rkhash_next(long long curr_hash, long long h, char leftmost, char rightmost)
{
return madd(msub(mmul(curr_hash, 256), mmul(leftmost, h)), rightmost);
}
madd, msub, and mmul are functions given to us by the professor. They perform modulus arithmetic after completing either addition, subtraction or multiplication. For example, here is the madd function:
long long madd(long long a, long long b)
{
return (a + b) % PRIME;
}
Can anyone please help me find out why my program is not working!?

Treating numeric overflow for pascal triangle

I am trying to create a large pascal triangle that prints up to 70 lines. My code works fine at first but it started to print out the wrong output when it reaches the 65th line. I know the problem to it and I've tried using GMP. Unfortunately the software that i use to code doesn't support GMP. Is there any other ways that i can do this without using GMP?
char str;
int value;
int pascal(int n)
{
for (int i = 1; i < n + 2; i++)
{
unsigned long number = 1;
for (int j = 1; j < i + 1; j++)
{
if(j == i)
{
printf("%lu\n", number);
}
else
{
printf("%lu ", number);
}
number = (number * (i - j) / j);
}
}
return 0;
}
Is there any other ways that i can do this without using GMP?
The integer math needed exceeds basic 64-bit math in forming numbers such as 109069992321755544170, a 67-bit number with more than 64 leading significant bits.
Although the widest integer uintmax_t may meet the more than 64-bit math needs, it is commonly only 64-bit.
long double often has a fair amount of precision (only 64-bit on my platform), but that is not specified to meet OP's need and invokes the usually FP issues of solving an integer problem.
Fortunately the extended math needed is only a multiply and divide. A simple, although not highly efficient, string multiply and divide meets the need.
void string_mult(char *y, unsigned x) {
size_t len = strlen(y);
unsigned acc = 0;
size_t i = len;
while (i > 0) {
i--;
acc += (y[i] - '0') * x;
y[i] = acc % 10 + '0';
acc /= 10;
}
while (acc) {
memmove(&y[1], &y[0], ++len);
y[0] = acc % 10 + '0';
acc /= 10;
}
}
unsigned string_div(char *y, unsigned x) {
size_t len = strlen(y);
unsigned acc = 0;
for (size_t i = 0; i < len; i++) {
acc *= 10;
acc += y[i] - '0';
y[i] = acc / x + '0';
acc %= x;
}
while (y[0] == '0' && len > 1) {
memmove(&y[0], &y[1], len);
len--;
}
return acc;
}
void pascal(unsigned n) {
printf("%u: ", n);
for (unsigned i = 1; i < n + 2; i++) {
char s[100] = "1";
for (unsigned j = 1; j <= i; j++) {
printf("%s ", s);
string_mult(s, i - j);
string_div(s, j);
}
printf("\n");
}
}
int main() {
for (unsigned i = 0; i <= 70; i++)
pascal(i);
}
Output
...
1 70 2415 54740 916895 12103014 131115985 1198774720 9440350920 65033528560 396704524216 2163842859360 10638894058520 47465835030320 193253756909160 721480692460864 2480089880334220 7877932561061640 23196134763125940 63484158299081520 161884603662657876 385439532530137800 858478958817125100 1791608261879217600 3508566179513467800 6455761770304780752 11173433833219812840 18208558839321176480 27963143931814663880 40498346384007444240 55347740058143507128 71416438784701299520 87038784768854708790 100226479430802391940 109069992321755544170 112186277816662845432 109069992321755544170 100226479430802391940 87038784768854708790 71416438784701299520 55347740058143507128 40498346384007444240 27963143931814663880 18208558839321176480 11173433833219812840 6455761770304780752 3508566179513467800 1791608261879217600 858478958817125100 385439532530137800 161884603662657876 63484158299081520 23196134763125940 7877932561061640 2480089880334220 721480692460864 193253756909160 47465835030320 10638894058520 2163842859360 396704524216 65033528560 9440350920 1198774720 131115985 12103014 916895 54740 2415 70 1
On further review, a long double may work, yet my efforts failed at pascal(69).

Resources