Reputation: 13
I am trying to implement a custom 1024 bit integer datatype in C. I want to implement operations like addition, subtraction and multiplication. Here is the structure I am defining:
typedef enum{POSITIVE, NEGATIVE} Sign;
typedef unsigned int uint32;
typedef struct int1024_tag {
Sign sign;
uint32* ints;
}bigInt;
Using this design allows me to efficiently store the integers in parts of 32 bits and operate on them efficiently.
However, as of now I need to input a hex string to initialize my bigInt
variables. I want to know if there is a way to input a decimal string like char input2_dec[] = "8902384390968597266"
and convert it into the string char input2_hex[] = "7B8B9F6FCDAA5B12"
so that I can pass them to my currently defined functions.
I tried converting digit by digit. But that approach fails as it involves computation with big numbers - and it beats the whole purpose of defining my own datatype and writing code for big number computation from scratch.
Upvotes: 1
Views: 108
Reputation: 153303
To parse a string in a wide integer:
parse as unsigned char to use is...()
functions.
(optional) look for leading white-space.
Look for a sign character.
Look for digits.
.. For each digit, scale the number by 10 and add the digit.
.. Watch for overflow
(optional) look for trailing white-space.
Examine the end.
#include <ctype.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct {
uint32_t ints[1024/32];
bool negsign;
} bigInt_alt;
bigInt_alt bigInt_from_string(const char *s) {
bigInt_alt y = { 0 };
const unsigned char *us = (const unsigned char *) s;
// Maybe toss leading whitespace
while (isspace(*us)) {
us++;
}
y.negsign = *us == '-';
if (y.negsign || *us == '+') {
us++;
}
if (!isdigit(*us)) {
; // TBD handle no digits
}
while (isdigit(*us)) {
unsigned carry = *us - '0';
for (size_t i = 0; i < 1024/32; i++) {
uint64_t acc = y.ints[i];
acc = acc * 10 + carry;
y.ints[i] = acc & 0xFFFFFFFF;
carry = (unsigned) (acc >> 32);
}
if (carry) {
; // TBD handle overflow
}
us++;
}
// Maybe allow trailing whitespace
while (isspace(*us)) {
us++;
}
if (*us != '\0') {
; // TBD handle junk input
}
return y;
}
Some unchecked template-like code that uses a fixed size integer array.
To do:
Fill in the TBD code.
Add a char **endptr
to record where parsing stopped, just like strtol()
.
Add a base to parse base 16, 2, etc., just like strtol()
.
For such wide input, consider allowing thousands separators ',' or the like.
Upvotes: 1
Reputation: 223689
Rather than convert the decimal string to a hex string, you can convert the decimal string directly.
Presumably you have a function that can convert an int
into a bigint
with one "digit". You can use this to convert individual decimal digits, then perform a multiply-by-10 and add loop for each digit.
Psedocode:
bigInt result = bigint_0;
char *p = input;
while (p) {
int value = *p - '0';
bigInt digit = new_bigint(value);
result = bigint_add(bigint_mult(result, bigint_10), digit);
p++;
}
Upvotes: 1