64-Bit Number Conversion Tool
Around 10 years ago I posted about a number conversion tool. Several improvements have made it into the tool in those years, so it's time for an update. The most notable change is the support for 64-bit resolution on the numbers (also when compiled on 32-bit systems). In addition there is support for more operators like and (&), or (|), multiplication (*), division (/) and modulus (%).
Here is the updated code:
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <limits.h> /* __WORDSIZE */ static uint64_t power_of_two(uint64_t n) { if (n == 0) return 1; else return 2 * power_of_two(n - 1); } static char *convert_to_bin(uint64_t integer) { static char buffer[65]; /* Should not be longer than 64-bits + NULL. */ int i, first_one; buffer[64] = '\0'; /* Always terminate. */ first_one = 63; for (i = 63; i >= 0; i--) { if (integer >= power_of_two(i)) { buffer[63 - i] = '1'; if (first_one > (63 - i)) { first_one = (63 - i); } integer -= power_of_two(i); } else { buffer[63 - i] = '0'; } } return &buffer[first_one]; } static uint64_t convert_from_bin(char *number) { uint64_t value; int n; char *p; value = 0; n = strlen(number) - 3; /* Also minus "0b". */ p = &number[2]; do { if (*p == '0') { n--; } else if (*p == '1') { value += power_of_two(n); n--; } } while (*p++ != '\0'); return value; } static uint64_t convert_to_int(char *number) { uint64_t integer; if (strncmp(number, "0x", 2) == 0) { integer = strtoull(number, NULL, 16); } else if (strncmp(number, "0b", 2) == 0) { integer = convert_from_bin(number); } else if (strncmp(number, "-", 1) == 0) { integer = atoll(number); /* Handle signed integers. */ } else { integer = strtoull(number, NULL, 10); } return integer; } static uint64_t biggest_int(uint64_t n1, uint64_t n2, uint64_t n3) { /* NOTE: Does not handle signed integers, so padding will be off. */ if (n1 > n2 && n1 > n3) { return n1; } else if (n2 > n3) { return n2; } else { return n3; } } static void display_int(uint64_t integer, char *prefix, uint64_t biggest) { int pad; if (prefix != NULL) { printf("%s", prefix); } #if (__WORDSIZE == 64) pad = snprintf(NULL, 0, "%ld", biggest) - snprintf(NULL, 0, "%ld", integer); #else /* __WORDSIZE == 32 */ pad = snprintf(NULL, 0, "%lld", biggest) - snprintf(NULL, 0, "%lld", integer); #endif /* __WORDSIZE */ while (pad-- > 0) { printf(" "); } #if (__WORDSIZE == 64) printf("%ld ", integer); #else /* __WORDSIZE == 32 */ printf("%lld ", integer); #endif /* __WORDSIZE */ printf("0x"); #if (__WORDSIZE == 64) pad = snprintf(NULL, 0, "%lx", biggest) - snprintf(NULL, 0, "%lx", integer); #else /* __WORDSIZE == 32 */ pad = snprintf(NULL, 0, "%llx", biggest) - snprintf(NULL, 0, "%llx", integer); #endif /* __WORDSIZE */ while (pad-- > 0) { printf("0"); } #if (__WORDSIZE == 64) printf("%lx ", integer); #else /* __WORDSIZE == 32 */ printf("%llx ", integer); #endif /* __WORDSIZE */ printf("0b"); pad = strlen(convert_to_bin(biggest)) - strlen(convert_to_bin(integer)); while (pad-- > 0) { printf("0"); } printf("%s\n", convert_to_bin(integer)); } int main(int argc, char *argv[]) { uint64_t n1, n2, result, biggest; char *prefix; if (argc == 2) { /* Just display the number in different forms. */ n1 = convert_to_int(argv[1]); display_int(n1, NULL, n1); } else if (argc == 4) { /* Perform extra operation. */ n1 = convert_to_int(argv[1]); n2 = convert_to_int(argv[3]); if (argv[2][0] == '+') { result = n1 + n2; prefix = " + "; } else if (argv[2][0] == '-') { result = n1 - n2; prefix = " - "; } else if (argv[2][0] == '^') { result = n1 ^ n2; prefix = " ^ "; } else if (argv[2][0] == '&') { result = n1 & n2; prefix = " & "; } else if (argv[2][0] == '|') { result = n1 | n2; prefix = " | "; } else if (argv[2][0] == '*') { result = n1 * n2; prefix = " * "; } else if (argv[2][0] == '/') { result = n1 / n2; prefix = " / "; } else if (argv[2][0] == '%') { result = n1 % n2; prefix = " % "; } else { fprintf(stderr, "%s: error: invalid operator.\n", argv[0]); return -1; } biggest = biggest_int(n1, n2, result); display_int(n1, " ", biggest); display_int(n2, prefix, biggest); display_int(result, " = ", biggest); } else { fprintf(stderr, "Usage: %s <number> [<operator> <number>]\n", argv[0]); fprintf(stderr, " number can be integer decimal, hex (0x) or binary (0b)\n"); fprintf(stderr, " valid operators: + - ^ & | * / %%\n"); return -1; } return 0; }