Iterating through digits in integer in C - c

I have an integer like 1191223
and I want to iterate over the digits. I am not sure how to do this in C, is there any easy way to do this?
Thanks.

Forwards, or backwards?
Assuming a positive integer:
unsigned int n = 1191223;
while (n != 0) {
doSomething (n % 10);
n /= 10;
}
…will work smallest to largest, or…
EDIT I'd forgotten all about this non-working solution I had here. Note that Very Smart People™ seem to use the smallest-to-largest iteration consistently (both Linux kernel and GLibC's printf, for example, just iterate backwards) but here's a lousy way to do it if you really don't want to use snprintf for some reason…
int left_to_right (unsigned int n) {
unsigned int digit = 0;
if (0 == n) {
doSomething (0);
} else {
digit = pow(10, 1.0+ floor(log10(n)));
while (digit /= 10) {
doSomething ( (n / digit) % 10 );
}
}
}
I assume that it's very silly to assume that you have log10 and pow but not snprintf, so an alternate plan would be
int left_to_right_fixed_max (unsigned int n) {
unsigned int digit = 1000000000; /* make this very big */
unsigned int n10 = 10 * n;
if (0 == n) {
doSomething (0);
} else {
while (digit > n10) { digit /= 10; }
while (digit /= 10) {
doSomething ( (n / digit) % 10 );
}
}
}
… or, if you really don't have hardware multiply/divide, you can resort to using a table of powers of ten.
int left_to_right (unsigned int n) {
static const unsigned int digit [] =
{ 1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000 /* make this very big */
};
static const unsigned char max_place = 10;
/* length of the above array */
unsigned char decimal;
unsigned char place;
unsigned char significant = 0; /* boolean */
if (0 == n) {
doSomething (0);
} else {
place = max_place;
while (place--) {
decimal = 0;
while (n >= digit[place]) {
decimal++;
n -= digit[place];
}
if (decimal | significant) {
doSomething (decimal);
significant |= decimal;
}
}
}
}
…which I have adapted from http://www.piclist.com/techref/language/ccpp/convertbase.htm into a somewhat more general-purpose version.

In the following I assume you mean decimal digits (base 10). Probably you are able to adapt the solutions to other numeral systems by substituting the 10s.
Note, that the modulo operation is a tricky thing concerning negative operands. Therefore I have chosen the data type to be an unsigned integer.
If you want to process the least significant digit first, you could try the following untested approach:
uint32_t n = 1191223;
do {
uint32_t digit = n%10;
// do something with digit
}
while (n/=10);
If you prefer to walk through the digits starting from the most significant digit, you could try to adapt the following untested code:
uint32_t n = 1191223;
#define MAX_DIGITS 10 // log10((double)UINT32_MAX)+1
uint32_t div = pow(10, MAX_DIGITS);
// skip the leading zero digits
while ( div && !(n/div) ) div/=10;
if ( !div ) div = 10; // allow n being zero
do {
uint32_t digit = (n/div)%10;
// do something with digit
}
while (div/=10);

You want to iterate over base-10 digits, but an integer has no concept of arabic notation and digits. Convert it to a string first:
int i = 1191223;
char buffer[16];
char *j;
snprintf(buffer, 16, "%i", i);
for ( j = buffer; *j; ++j ) { /* digit is in *j - '0' */ }

You can use sprintf() to convert it into a char array, and then iterate through that, like so (untested, just to get you started):
int a = 1191223;
char arr[16];
int rc = sprintf(arr, "%d", a);
if (rc < 0) {
// error
}
for (int i = 0; i < rc; i++) {
printf("digit %d = %d\n", i, arr[i]);
}

void access_digits(int n)
{
int digit;
if (n < 0) n = -n;
do {
digit = n % 10;
/* Here you can do whatever you
want to do with the digit */
} while ((n/=10) > 0);
}

Something like this:
char data[128];
int digits = 1191223;
sprintf(data, "%d", digits);
int length = strlen(data);
for(int i = 0; i < length; i++) {
// iterate through each character representing a digit
}
Notice that if you use an octal number like 0100 you also need to change the sprintf(data, "%d", digits); to sprintf(data, "%o", digits);.

For my purposes the following short code did the trick.
Having a an integer variable the_integer, and an integer variable sum_of_digits initialized. (line 1) You could do the following:
1) Convert the integer variable to a variable of type string with use of the std::to_string(int) function.
2) Iterate of the characters of the resulting string. for(char& c: str::to_string(the_integer))
3) To convert the characters back to integers use c -'0' . For this solution take a look at the discussion in (Convert char to int in C and C++).
4) .. and adding them the digits together: sum_of_digits += c-'0'
*) you can then print your variables: lines 3 and 4.
int the_integer = 123456789; int sum_of_digits;
for (char& c: std::to_string(the_integer)) {sum_of_digits += c-'0';}
std::cout << "Integer: " << the_integer << std::endl;
std::cout << "Sum of Digits << sum_of_digits << std::endl;
Note that std::to_string() has some notes, please consult the c++ references to see if the code is still relevant for your purposes.

A hackish way is to convert this to string (see strtol) and then reconvert this to a number.
you could use something like character you want - '0'

Off the top of my head: "i % 100000", "i % 100000", ...
A recursive solution would let you start from "i%10".

Related

My decimal to hex conversion function only woks with positive nums

I'm having problems converting negative numbers, from decimal base to hexadecimal base, with the following function:
#include <stdio.h>
int main()
{
int quotient, remainder;
int i, j = 0;
char hexadecimalnum[100];
quotient = -50;
while (quotient != 0)
{
remainder = quotient % 16;
if (remainder < 10)
hexadecimalnum[j++] = 48 + remainder;
else
hexadecimalnum[j++] = 55 + remainder;
quotient = quotient / 16;
}
strrev(hexadecimalnum);
printf("%s", hexadecimalnum);
return 0;
}
For quotient = -50; the correct output should be:
ffffffce
But this function's output is:
.
With positive numbers the output is always correct but with negative numbers not.
I'm having a hard time understanding to why it doesn't work with negative numbers.
Some fixes:
unsigned int quotient - you need to convert -50 to a large hex number in two's complement or you'll get the wrong number of iterations (2) in the loop, instead of 8 as required.
Removal of "magic numbers": '0' + remainder and 'A' + remainder - 10.
Zero initialize hexadecimalnum becaues it needs to be null terminated before printing a string from there. Better yet, add the null termination explicitly.
Use for loops when possible.
Might as well store the characters from the back to front and save the extra call of reversing the string.
Result:
#include <stdio.h>
// 4 bytes*2 = 8 nibbles
#define HEX_STRLEN (sizeof(int)*2)
int main()
{
unsigned int remainder;
int i = 0;
char hex[100];
for(unsigned int q = -50; q!=0; q/=16)
{
remainder = q % 16;
if (remainder < 10)
hex[HEX_STRLEN-i-1] = '0' + remainder;
else
hex[HEX_STRLEN-i-1] = 'A' + remainder - 10;
i++;
}
hex[HEX_STRLEN] = '\0'; // explict null termination
printf("%s\n", hex);
}
(There's lots of improvements than can be made still, this is just to be considered as the first draft.)
You can use printf's format specifier "%08x", then you can print any number in their respective hexadecimal representation.
#include <stdio.h>
void num_to_hex(int a, char *ptr) { snprintf(ptr, 9, "%08x", a); }
int main() {
char hex[10] = {};
num_to_hex(-50, hex);
printf("%s\n", hex);
return 0;
}
Output:
ffffffce

How to print values in reverse without the use of arrays nor pointers in C

I've been working on a code that converts a given number (decimal base) to any other base from 2 to 16.
Clearly, I've come across the issue that the function base_conversion_it (it stands for iterative) prints the values in reverse.
I cannot use arrays nor pointers, and everyone on the internet seems to solve this issue like that. My assignment requires making both an iterative and a recursive function (which I did and works).
void base_conversion_it(unsigned int n, unsigned int b) {
if (n > 0) {
//bases between 2 and 16
if (b >= 2 && b <= 16) {
int r; //r = remainder
int q = 1; //quotient
int num; //saves the remainder
while (q != 0) {
r = n % b;
printf("%X", r);
q = n / b;
n = q;
}
}
}
}
You start converting from the units digit.
Maybe start with the most significant digit instead?
// It's Undefined Behaviour if `b` is outside the range [2...16]
void base_conversion_it(unsigned int n, unsigned int b) {
unsigned highestbase = 1;
while (highestbase * b <= n) highestbase *= b; //possible wrap around and infinite loop
while (highestbase) {
printf("%X", n / highestbase);
n %= highestbase;
highestbase /= b;
}
printf("\n");
}
Sorry missed iterative.
char digits[] = "0123456789ABCDEFGHIJKLMNOP";
void print(unsigned long long val, unsigned base)
{
unsigned long long mask = base;
while(val / mask >= base) mask *= base;
do
{
printf("%c", digits[val / mask]);
val %= mask;
mask /= base;
}while(val);
}
int main(void)
{
print(45654756453, 10); printf("\n");
print(45654756453, 16); printf("\n");
print(45654756453, 24); printf("\n");
print(45654756453, 2); printf("\n");
}
https://godbolt.org/z/W3fGnnhYs
Recursion:
char digits[] = "0123456789ABCDEF";
void print(unsigned long long val, unsigned base)
{
if(base <= 16 && base > 1)
{
if(val >= base) print(val / base, base);
printf("%c", digits[val % base]);
}
}
https://godbolt.org/z/84hYocnjv
If you cannot use either arrays (including strings) or recursion, then I think you need to compute the output digits in most-significant-first order. This is a bit less natural than computing them in the opposite order and reversing the result, but it can be done:
use a loop to find the place value of the most significant non-zero base-b digit of n. For example, check the result of dividing n by successive powers of b until the result is 0, then back off one step.
In a separate loop, read off the base-b digits of n one by one, starting with the one at the discovered most-significant position. For each digit,
Divide the current value of n by the place value pv of the current digit to get a digit value.
Replace n with n % pv.
Be careful to continue all the way down to place value 1, as opposed, say, to stopping when n becomes zero.

How to do binary addition of real numbers?

Short story. I made a program that does addition for binary integers. I need to make it work for binary real numbers (e.g. 1010.1010(binary)=10.625(decimal)
The input is given as a binary string.
I made a lot of attempts and I couldn't find a simple way to do it. Please help create such a program.
Example: {input: 1010.1010(10.625 in decimal) 0.1(0.5 in decimal)
output: 1011.001 (11.125 in decimal)}
Code:
#include <stdio.h>
#include <string.h>
void bin_add(int c[400], int d[400])
{
int car[400]; //carry
int i = 199;
car[i] = 0;
while (i >= 0)
{
//find carry and shift it left
//find the sum
car[i - 1] = (c[i] & d[i]) | (c[i] & car[i]) | (d[i] & car[i]);
c[i] = (c[i] ^ d[i]) ^ car[i];
printf("car[i-1]=%d c[i]=%d\n", car[i - 1], c[i]);
i--;
}
// printf("\n");
}
int main()
{
int l, l1, i;//l and l1 are lengths
char a[200], b[200]; //a and b are the inputs
int c[200], d[200]; //c and d are used for processing
for (i = 0; i < 200; i++)
{
c[i] = 0;
d[i] = 0;
}
gets(a);
gets(b);
l = strlen(a);
l1 = strlen(b);
for (int i = 0; i < l; i++)
{
c[200 - l + i] = a[i] - 48;
}
////////////////////////////////////////////
for (int i = 0; i < l1; i++)
{
d[200 - l1 + i] = b[i] - 48;
}
////////////////////////////////
bin_add(c, d);
for (i = 0; i < 200; i++)
printf("%d", c[i]);
return 0;
}
What you really want to do, is handle each digit in order of increasing importance. To make that easier, you should implement the following functions:
/* Return the number of fractional bits in bs */
int bs_fractbits(const char *bs);
/* Return the number of integer bits in bs */
int bs_intbits(const char *bs);
/* Return the bit in bs corresponding to value 2**i,
0 if outside the bit string */
int bs_bit(const char *bs, int i);
/* Return -1 if bs is negative,
0 if bs is zero or NULL,
+1 if bs is positive */
int bs_sign(const char *bs);
/* Return -1 if bs1 < bs2,
0 if bs1 == bs2,
+1 if bs1 > bs2. */
int bs_cmp(const char *bs1, const char *bs2);
To support negative values, you'll need to implement both addition and subtraction (of "unsigned" bit strings):
Addition: The result has as many fractional bits as the term that has most fractional bits, and possibly one more integer bit than the term that has most integer bits. Start at the least significant bit in either term, and work your way up to the most significant bit in either term, summing each bit, and keeping the "carry bit" along, just like you'd do by hand. If the carry is nonzero at end, you'll get that one additional bit.
Subtraction: Always subtract smaller from larger. If that changes the order of the terms, negate the result. The result has at most as many fractional bits as the term that has most fractional bits, and at most as many integer bits as the term that has most integer bits. This is just like addition, except you subtract the bits, and instead of "carry bit", you use a "borrow bit". Because you subtract smaller unsigned value from larger unsigned value, the "borrow bit" will be zero at end.
Multiplication: The integer part has the number of integer bits, and the number of fractional bits, as the terms have in total (summed). You can implement the operation as if multiplying two unsigned integer values, and just insert the bit at end. (So that the result has as many fractional bits as the input terms have in total.) This usually involves a double loop, just like in long multiplication by hand.
Note that the same logic also works if you use larger radix instead of 2. The "carry"/"borrow" is a digit, between zero and one less than the radix.
Personally, I'd be very tempted to use a structure to describe each digit string:
typedef struct {
int idigits; /* Number of integral digits before point */
int fdigits; /* Number of fractional digits after point */
int size; /* Number of chars dynamically allocated at data */
char *point; /* Location of decimal point */
char *data; /* Dynamically allocated buffer */
} digitstring;
#define DIGITSTRING_INIT { 0, 0, 0, NULL, NULL }
with an additional flag if negative digit strings are to be supported.
Digit D with numerical value D×Bi, where B is the radix (number of unique digits used) and i being the position of said digit, is located at point[-i] if i < 0 (and -i <= fdigits), or at point[-i-1] if i >= 0 (and i < idigits). point[0] itself is where the decimal point is, if there is one.
For example, if we have string 0100.00, then idigits = 4, fdigits = 2, and the only nonzero digit is at position 2. (Position 0 is on the left side of the decimal point, and -1 on the right side.)
size and data fields allow reuse of the dynamically allocated buffer. Each declaration of a digitstring must be initialized, digitstring value = DIGITSTRING_INIT;, because there is no initialization function; this way you are less likely to leak memory (unless you forget to free a digitstring when no longer needed):
/* Free the specified digit string. */
static inline void digitstring_free(digitstring *ds)
{
if (ds) {
if (ds->data)
free(ds->data);
ds->idigits = 0;
ds->fdigits = 0;
ds->size = 0;
ds->point = NULL;
ds->data = NULL;
}
}
To use the digit string as a C string, you use a helper function to obtain the pointer to the most significant digit in the digit string:
/* Return a pointer to a printable version of the digit string. */
static const char *digitstring_str(const digitstring *ds, const char *none)
{
if (ds && ds->point)
return (const char *)(ds->point - ds->idigits);
else
return none;
}
I've found that rather than crash, it is often useful to pass an extra parameter that is only used for the return value when the return value is otherwise undefined. For example, if you have an initialized digit string foo without any contents, then digitstring_str(&foo, "0") returns the string literal "0".
The main point of the digit string structure is to have accessor functions that get and set each individual digit:
/* Get the value of a specific digit. */
static inline unsigned int digitstring_get(const digitstring *ds, const int position)
{
if (ds) {
if (position < 0) {
if (-position <= ds->fdigits)
return digit_to_value(ds->point[-position]);
else
return 0;
} else {
if (position < ds->idigits)
return digit_to_value(ds->point[-position-1]);
else
return 0;
}
} else
return 0;
}
/* Set the value of a specific digit. */
static inline void digitstring_set(digitstring *ds, const int position, const unsigned int value)
{
if (!ds) {
fprintf(stderr, "digitstring_set(): NULL digitstring specified.\n");
exit(EXIT_FAILURE);
} else
if (position < 0) {
if (-position > ds->fdigits) {
fprintf(stderr, "digitstring_set(): Digit position underflow (in fractional part).\n");
exit(EXIT_FAILURE);
}
ds->point[-position] = value_to_digit(value);
} else {
if (position >= ds->idigits) {
fprintf(stderr, "digitstring_set(): Digit position overflow (in integer part).\n");
exit(EXIT_FAILURE);
}
ds->point[-position-1] = value_to_digit(value);
}
}
Above, value_to_digit() is a helper function that converts a numerical value to the corresponding character, and digit_to_value() converts a character to the corresponding numerical value.
All operations (from parsing to arithmetic operators) really need a "constructor", that creates a new digit string with sufficient number of digits. (The number of digits is known beforehand for each operation, and depends only on the number of significant digits in the terms.) For this, I created a function that constructs a zero of desired size:
/* Clear the specified digit string to zero. */
static inline void digitstring_zero(digitstring *ds, int idigits, int fdigits)
{
int size;
char *data;
if (!ds) {
fprintf(stderr, "digitstring_zero(): No digitstring specified.\n");
exit(EXIT_FAILURE);
}
/* Require at least one integral digit. */
if (idigits < 1)
idigits = 1;
if (fdigits < 0)
fdigits = 0;
/* Total number of chars needed, including decimal point
and string-terminating nul char. */
size = idigits + 1 + fdigits + 1;
/* Check if dynamically allocated buffer needs resizing. */
if (ds->size < size) {
if (ds->data)
data = realloc(ds->data, size);
else
data = malloc(size);
if (!data) {
fprintf(stderr, "digitstring_zero(): Out of memory.\n");
exit(EXIT_FAILURE);
}
ds->data = data;
ds->size = size;
} else {
data = ds->data;
size = ds->size;
}
/* Fill it with zeroes. */
memset(data, value_to_digit(0), idigits + 1 + fdigits);
/* Pad the unused space with nul chars, terminating the string. */
memset(data + idigits + 1 + fdigits, '\0', size - idigits - 1 - fdigits);
/* Assign the decimal point. */
ds->point = data + idigits;
/* If there are no decimals, no need for a decimal point either. */
if (fdigits > 0)
ds->point[0] = decimal_point;
else
ds->point[0] = '\0';
/* After setting the desired digits, use digitstring_trim(). */
ds->idigits = idigits;
ds->fdigits = fdigits;
}
It will ensure the digit string has enough room for the specified number of digits, reallocating its dynamically allocated buffer if necessary, reusing it if already large enough.
The idea is that to implement an operation, you first find out the maximum number of integral and fractional digits the result can have. You use the above to create the result digit string, then digitstring_set() to set each digit to their respective values. You will typically operate in increasing digit significance, which means increasing digit "positions".
If we have additional helper functions int digits(const char *src), which returns the number of consecutive valid digit characters starting at src, and int decimal_points(const char *src), which returns 1 if src points to a decimal point, and 0 otherwise, we can parse input strings into digit strings using
/* Parse a string into a digit string, returning the pointer
to the first unparsed character, or NULL if an error occurs. */
static const char *digitstring_parse(digitstring *ds, const char *src)
{
const int zero = value_to_digit(0);
const char *idigit, *fdigit;
int idigits, fdigits, fextra, n;
/* Fail if nothing to parse. */
if (!src)
return NULL;
/* Skip leading whitespace. */
while (isspace((unsigned char)(*src)))
src++;
/* Fail if nothing to parse. */
if (*src == '\0')
return NULL;
/* Scan integer digits. */
idigit = src;
src += digits(src);
idigits = (int)(src - idigit);
/* Decimal point? */
fextra = 0;
n = decimal_points(src);
if (n > 0) {
src += n;
/* Scan fractional digits. */
fdigit = src;
src += digits(src);
fdigits = (int)(src - fdigit);
if (fdigits < 1)
fextra = 1;
} else {
fdigit = src;
fdigits = 0;
}
/* No digits? */
if (idigit == 0 && fdigit == 0)
return NULL;
/* Trim leading zeroes. */
while (idigits > 1 && *idigit == zero) {
idigits--;
idigit++;
}
/* Trim trailing zeroes. */
while (fdigits > 1 && fdigit[fdigits - 1] == zero)
fdigits--;
/* Create the necessary digit string, */
digitstring_zero(ds, idigits, fdigits + fextra);
/* copy the integer digits, if any, */
if (idigits > 0)
memcpy(ds->point - idigits, idigit, idigits);
/* and the fractional digits, if any. */
if (fdigits > 0)
memcpy(ds->point + 1, fdigit, fdigits);
/* Return a pointer to the first unparsed character. */
return src;
}
After updating its digits, one can call a helper function to remove any extra leading zeroes:
static inline void digitstring_ltrim(digitstring *ds)
{
if (ds && ds->point) {
const int zero = value_to_digit(0);
while (ds->idigits > 1 && ds->point[-ds->idigits] == zero)
ds->idigits--;
}
}
Adding two (unsigned) digit strings, possibly reusing one of the terms, is now quite simple to implement:
static void digitstring_add(digitstring *to, const digitstring *src1, const digitstring *src2)
{
digitstring result = DIGITSTRING_INIT;
unsigned int carry = 0;
int i, idigits, fdigits;
if (!to || !src1 || !src2) {
fprintf(stderr, "digitstring_add(): NULL digitstring specified.\n");
exit(EXIT_FAILURE);
}
/* For addition, the result has as many digits
as the longer source term. */
idigits = (src1->idigits >= src2->idigits) ? src1->idigits : src2->idigits;
fdigits = (src1->fdigits >= src2->fdigits) ? src1->fdigits : src2->fdigits;
/* Result needs possibly one more integer digit,
in case carry overflows. */
digitstring_zero(&result, idigits + 1, fdigits);
/* Addition loop, in order of increasing digit significance. */
for (i = -fdigits; i < idigits; i++) {
const unsigned int sum = digitstring_get(src1, i)
+ digitstring_get(src2, i)
+ carry;
digitstring_set(&result, i, sum % RADIX);
carry = sum / RADIX;
}
digitstring_set(&result, idigits, carry);
/* Trim leading zeroes. */
digitstring_ltrim(&result);
/* At this point, we can discard the target, even if it is actually
one of the sources, and copy the result to it. */
digitstring_free(to);
*to = result;
}
where RADIX is the radix used (the number of unique digits, 2 for binary). Pay extra attention to the digit loop. -fdigits is the least significant position in the result, and idigits-1 the most significant position. We need the accessor functions, because the source terms might not contain those digits at all (they are logically zero then).
These functions have been tested to work on both binary and octal number strings. I like this implementation, because it omits the decimal point if all terms are integers (so you get 12 + 33 = 45), but (due to fextra in digitstring_parse()) if any of the terms have a decimal point, then the result will have at least one fractional digit (so 12. + 33 = 45.0).
After all the beautiful ideas in Animals' answer I felt the strange urge, to present my own solution:
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX(x, y) ((x) > (y) ? (x) : (y))
size_t gpp(char const *s)
{
char *n = strchr(s, '.');
return n ? n - s + 1 : 0;
}
char* bin_add(char const *a, char const *b)
{
char const *inp[] = { a, b };
size_t ll[] = { strlen(a), strlen(b) };
size_t pp[] = { gpp(a), gpp(b) };
size_t OO[2], off[2];
for (size_t i = 0; i < 2; ++i) {
OO[i] = pp[i] ? pp[i] - 1 : ll[i];
pp[i] = pp[i] ? ll[i] - pp[i] : 0;}
for (size_t i = 0; i < 2; ++i)
off[i] = OO[i] < OO[!i] ? OO[!i] - OO[i] : 0;
size_t ML = MAX(OO[0], OO[1]) + MAX(pp[0], pp[1]) + (!!pp[0] || !!pp[1]);
char *Ol = calloc(ML + 2, 1);
if(!Ol) return Ol;
char ops[2];
int xc = 0;
size_t lO = ML;
unsigned cc[2] = { 0 };
for (size_t i = ML; i; --i) {
bool pt = false;
for (size_t l = 0; l < 2; ++l) {
ops[l] = i <= ll[l] + off[l] && i - off[l] - 1
< ll[l] ? inp[l][i - off[l] - 1] : '0';
if (ops[l] == '.') {
if (cc[l]) {
free(Ol);
return NULL;
}
pt = true;
++cc[l];
}
ops[l] -= '0';
}
if (pt) {
Ol[i] = '.';
continue;
}
if ((Ol[i] = ops[0] + ops[1] + xc) > 1) {
Ol[i] = 0;
xc = 1;
}
else xc = 0;
lO = (Ol[i] += '0') == '1' ? i : lO;
}
if((Ol[0] = '0' + xc) == '1') return Ol;
for (size_t i = 0; i <= ML - lO + 1; ++i)
Ol[i] = Ol[lO + i];
return Ol;
}
int main(void)
{
char a[81], b[81];
while (scanf(" %80[0.1] %80[0.1]", a, b) & 1 << 1) {
char *c = bin_add(a, b);
if (!c && errno == ENOMEM) {
fputs("Not enough memory :(\n\n", stderr);
return EXIT_FAILURE;
}
else if (!c) {
fputs("Input error :(\n\n", stderr);
goto clear;
}
char* O[] = { a, b, c };
size_t lO[3], Ol = 0;
for (size_t i = 0; i < 3; ++i) {
lO[i] = gpp(O[i]);
lO[i] = lO[i] ? lO[i] : strlen(i[O]) + 1;
Ol = lO[i] > Ol ? lO[i] : Ol;
}
putchar('\n');
for (size_t i = 0; i < 3; ++i) {
for (size_t l = 0; l < Ol - lO[i]; ++l, putchar(' '));
puts(O[i]);
}
putchar('\n');
free(c);
clear :{ int c; while ((c = getchar()) != '\n' && c != EOF); }
}
}
Sample Output:
11001001 .11001001
11001001
.11001001
11001001.11001001
11001001 1010
11001001
1010
11010011
111111 1
111111
1
1000000
1010101 010111001.0101110101010
1010101
010111001.0101110101010
100001110.0101110101010
1001001.010111010101 10100101100.10010111101
1001001.010111010101
10100101100.10010111101
10101110101.111000001111
. .
.
.
0
.. .
Input error :(
A
Press any key to continue . . .
I contemplated wheter I should ask for a review at codereview. But I think I schould rather not.
There are two answers, depending upon whether you desire fixed- or floating- point arithmetic.
The first issue is reading the number. strtol() is your friend here:
char input[BUFFER_SIZE];
char * tmp;
long integral, fractional;
fgets(input, BUFFER_SIZE-1, stdin);
integral = strtol(input, &tmp, 2); /* Read BINARY integral part */
tmp++; /* Pass over the binary point. You may want to check that it is actually a dot */
fractional = strtol(tmp, null, 2); /* Read BINARY fractional part */
The next issue is figuring out how you will do the arithmetic. fractional must be bit-shifted an amount depending on how many digits past the point were provided and your desired precision. Fixed point arithmetic is simple: fractional <<= FRAC_BITS - strlen(tmp) then add the fractional parts together. Mask by ((1<<FRAC_BITS)-1) for the fractional part of the sum, shift the remaining bits and add them to the integral parts for the integral part of the sum. Floating-point is a little more finicky, but not too much harder.
For real numbers, convert non-fraction and fraction part to decimal, do the addition and print it as binary. This will require function to convert a number to binary string. Just a note that real numbers are float numbers in C and they are represented in binary with mantessa form like 2e^3 which is 2 multiplied by exponent to the power of 3.

Bitand function in C

I want to make a bitwise AND computation over integers, but without converting them to binary numbers. For example, I have a integer "10111" (it is integer, not binary) and another integer "01001". I want bitwise AND of these numbers without converting them to binary and then making bitwise AND. I know it is not bitwise what I ask, but I want something similar to this. I know it can be interpreted initially as binary, converted to decimal and then do bitwise AND, but I do not want that. I want something like this:
int a;
int b;
int temp;
double result;
temp = a & b;
while (result != 0) {
if (result % 10 == 1)
count++;
result /= 10;
}
int length = floor(log10(abs(a))) + 1;
result = count / length;
return result;
I want this to check similarity of the Bag of Words(from natural language processing, string of 0s and 1s). I am importing Bag of Words in Monetdb, Column type should be Integer (Not string). If I have for example "10111" and "01001" in the Integer type cells, I want to get "00001" and fraction 1/5, because only 1 positions matches.
Thanks in advance
Might be a bit bulky, but it kind of works) You can optimize it yourself. I hope that I get you correctly.
IDEOne demo
#include <stdio.h>
unsigned int weirdAnd(unsigned int a, unsigned int b) {
unsigned int result = 0;
unsigned int coef = 1;
while (a && b) {
result += ((a % 10) && (b % 10)) * coef;
coef *= 10;
a /= 10;
b /= 10;
}
return result;
}
unsigned int weirdOr(unsigned int a, unsigned int b) {
unsigned int result = 0;
unsigned int coef = 1;
while (a || b) {
result += ((a % 10) || (b % 10)) * coef;
coef *= 10;
a /= 10;
b /= 10;
}
return result;
}
int main(void) {
// your code goes here
unsigned int a = 10110;
unsigned int b = 10011;
printf("%u and \n%u = \n%u\n\n", a, b, weirdAnd(a, b));
printf("%u or \n%u = \n%u\n\n", a, b, weirdOr(a, b));
return 0;
}
Output:
10110 and 10011 = 10010
10110 or 10011 = 10111
The problem is that and works on bits only, and it does not care if the input numbers are given in decimals, octal, hexadecimal, or any other way. To force and to work correctly, you must give it an input in 'binary', that is, only ones and zeroes. To do so you need to grab each digit of the input numbers as if they are binary digits.
The following works as expected:
#include <stdio.h>
int cheap_pow (int base, int exponent)
{
int result = base;
while (exponent-- > 0)
result *= base;
return result;
}
int main (void)
{
int a = 10111, b = 1001 ;
int result, factor;
printf ("BAD: %05d AND %05d = %05d\n", a, b, a & b);
printf ("GOOD: %05d AND %05d = ");
result = 0;
factor = 1;
while (a | b)
{
result += factor * ((a & 1) and (b & 1));
factor *= 10;
a /= 10;
b /= 10;
}
printf ("%05d\n", result);
}
but you must be careful when defining your inputs. When written directly into your source code, a value b = 01001 will be interpreted by the C compiler as octal (base 8), rather than decimal; and it will have the (decimal) value 513. It's just a Rule of C.
If your input comes from elsewhere, you don't need to take this into account – except when you use a standard function such as strtol, where you should carefully read the documentation because it does the same thing:
If base is zero or 16, the string may then include a "0x"
prefix, and the number will be read in base 16; otherwise, a zero
base is taken as 10 (decimal) unless the next character is '0', in
which case it is taken as 8 (octal).
An additional note is this program only will work in the range for signed int, that is (currently) up to 10 "binary" digits. If you need some more, you could switch to a larger type; but beyond that, you are better off with a not-numerical solution and use a character strings throughout.
int a, b;
int tmp = a & b;
int res = 0;
while ((tmp != 0 &&) (tmp / 10 != 0)){
int dig = tmp % 10;
res = (dig == 1)? ++res: res;
tmp /= 10;
}
Try this.

Any decent way of printing out floats and doubles with commas?

I'm working on a program that regards with currency. Ive been finding a solution to display money values decently like this:
9,999.99 USD
Remember when assigning a certain variable with a value (money), you musn't insert commas.
I.e.:
double money=9999.99;
And when accessing it;
printf("%.2l USD",money);
Which will output:
9999.99 USD
This is not what I want, especially on bigger amounts exceeding the hundredth, thousandth, millionth, or even billionth place value.
Now I can't find any solution than printing out the desired output directly on the printf.
printf("9,999.99");
Which is undesirable with many variables.
Can anyone help me out?
Please take a look and printf manual page taking note of the following bit:
*"For some numeric conversions a radix character ("decimal point") or thousands' grouping character is used. The actual character used depends on the LC_NUMERIC part of the locale. The POSIX locale uses '.' as radix character, and does not have a grouping character. Thus,
printf("%'.2f", 1234567.89);
results in "1234567.89" in the POSIX locale, in "1234567,89" in the nl_NL locale, and in "1.234.567,89" in the da_DK locale."*
This can be changed by the function setlocale
There is a function, strfmon which might be able to help you
First, don't use floating-point types to represent money because normally floating-point types are binary and as such cannot represent all decimal fractions (cents) exactly, further these types are prone to rounding errors. Use integers instead and count cents instead of dollars.
#include <stdio.h>
#include <limits.h>
unsigned long long ConstructMoney(unsigned long long dollars, unsigned cents)
{
return dollars * 100 + cents;
}
void PrintWithCommas(unsigned long long n)
{
char s[sizeof n * CHAR_BIT + 1];
char *p = s + sizeof s;
unsigned count = 0;
*--p = '\0';
do
{
*--p = '0' + n % 10;
n /= 10;
if (++count == 3 && n)
{
*--p = ',';
count = 0;
}
} while (n);
printf("%s", p);
}
void PrintMoney(unsigned long long n)
{
PrintWithCommas(n / 100);
putchar('.');
n %= 100;
putchar('0' + n / 10);
putchar('0' + n % 10);
}
int main(void)
{
PrintMoney(ConstructMoney(0, 0)); puts("");
PrintMoney(ConstructMoney(0, 1)); puts("");
PrintMoney(ConstructMoney(1, 0)); puts("");
PrintMoney(ConstructMoney(1, 23)); puts("");
PrintMoney(ConstructMoney(12, 34)); puts("");
PrintMoney(ConstructMoney(123, 45)); puts("");
PrintMoney(ConstructMoney(1234, 56)); puts("");
PrintMoney(ConstructMoney(12345, 67)); puts("");
PrintMoney(ConstructMoney(123456, 78)); puts("");
PrintMoney(ConstructMoney(1234567, 89)); puts("");
return 0;
}
Output (ideone):
0.00
0.01
1.00
1.23
12.34
123.45
1,234.56
12,345.67
123,456.78
1,234,567.89
If you're using the standard library, there's no way to do this -- you have to write some code that does it by hand.
I would recommend multiplying the value by 100, casting to integer, and printing the digits with separators as needed -- it's much easier to handle individual digits on an integer.
The following code, for instance, will fill a char * buffer with the string representation of the value you have:
void formatString (double number, char * buffer) {
if (number < 0) {
*buffer = '-';
formatString(number, buffer + 1);
return;
}
unsigned long long num = (unsigned long long) (number * 100);
unsigned long long x; // temporary storage for counting the digits
unsigned char digits;
for (x = num / 1000, digits = 1; x; digits ++, x /= 10);
// counts the digits, also ensures that there's at least one digit
unsigned char pos; // digit position
for (pos = 1, x = 100; pos < digits; pos ++, x *= 10);
// reuses x as a value for extracting the digit in the needed position;
char * current = buffer;
for (pos = digits; pos; pos --) {
*(current ++) = 48 + (num / x);
// remember 48 + digit gives the ASCII for the digit
if (((pos % 3) == 1) && (pos > 1)) *(current ++) = ',';
num %= x;
x /= 10;
}
*(current ++) = '.';
*(current ++) = 48 + num / 10;
*(current ++) = 48 + num % 10;
*current = 0;
}

Resources