8

Question

  • Is there a way to create a arbitrary size integer using c/c++?

For example:

int main(void) {
  Int i = Int(3); //3-bit integer
  i = 1; //Represented as: 001
}

Bonus

  • Is there a way to do the same with floating values?
Community
  • 1
  • 1
Simón Oroño
  • 1,060
  • 3
  • 14
  • 24
  • 1
    You can write a class that does this. – user253751 Feb 23 '15 at 23:49
  • 2
    Not individually, but as part of a struct or class: [bit field](http://en.cppreference.com/w/cpp/language/bit_field) – Mark Ransom Feb 23 '15 at 23:52
  • 1
    You'd have a stack overflow if you tried to do `1/3` in an arbitrary-sized floating point class ! – MSalters Feb 24 '15 at 00:09
  • 1
    Take a look here for small arbitrary size integers: http://stackoverflow.com/questions/11815894/how-to-read-write-arbitrary-bits-in-c-c/27592777#27592777 , that is if you are interested in saving memory (bit packing comes at a small performance penalty). For bigger than the standard types you'd probably be better off using some library. – dtech Feb 24 '15 at 00:26
  • This post is way too broad: question about variant bit lengths, variant byte length and additional various floating point. Try just 1 of those 3 and be explicit about the needed for sign-ness to get quality answers. – chux - Reinstate Monica Feb 24 '15 at 01:06
  • @chux I think is very clear that I'm asking for variant bit lengths, the floating point part is just curiosity – Simón Oroño Feb 24 '15 at 01:28
  • If you want to perform the multi-precision math yourself, then I suggest you take a look at Donald Knuth's [Art of Computer Programming](https://en.wikipedia.org/wiki/The_Art_of_Computer_Programming). I believe Volume II, Seminumerical Algorithms, Chapter 4, Multiple Precision Arithmetic, is what you are interested in. Also see [How to add 2 arbitrarily sized integers in C++?](https://stackoverflow.com/q/2926219/608639), which provides code for some C++ libraries and OpenSSL. – jww Aug 29 '17 at 17:46
  • 1
    FYI, there is a C23 proposal (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2709.pdf "Adding a Fundamental Type for N-bit integers") for adding them via `_BitInt(3)`. If it's approved, this may be an additional future answer. – Dwayne Robinson Dec 21 '21 at 12:15

5 Answers5

9

You can't create integers of size less than char (that is, each object has a size in bytes that's a multiple of sizeof(char), which is 1). But that's not a problem since you can pack numbers inside a larger number.

const unsigned size_in_bits = 3;
unsigned a = 1; // 001
unsigned b = 5; // 101
unsigned packed = (b << size_in_bits*1) | (a << size_in_bits*0); // 101001
unsigned unpacked_a = (packed >> size_in_bits*0) & ((1 << size_in_bits)-1);
unsigned unpacked_b = (packed >> size_in_bits*1) & ((1 << size_in_bits)-1);

or use bitfields (the syntax is nicer, but the binary layout is implementation-defined)

struct Date
{
    unsigned day : 5;
    unsigned month : 4;
    unsigned year : 21; 
};

Date d;
d.day = 5; d.month = 11; d.year = 2014;
milleniumbug
  • 15,379
  • 3
  • 47
  • 71
  • could you please elaborate on "binary layout is implementation-defined"? – Simón Oroño Feb 24 '15 at 00:47
  • @SimonOroño - there is no guarantee different compilers will produce the same layout. The standard leaves that "unstandardized" for compatibility with exotic platforms long gone. If you want portability, you better write your own "manual bitfields" as described in the question I linked in the comments above. – dtech Feb 24 '15 at 00:51
5

You could try the GNU Multiple Precision Arithmetic Library library, which supports both integers, fractions, and real numbers.

Aasmund Eldhuset
  • 37,289
  • 4
  • 68
  • 81
  • 1
    Can I create a fixed size integer with gmp? For what I'm reading this creates python-like integers that grow as long as they have the memory required. – Simón Oroño Feb 24 '15 at 00:09
  • @SimonOroño: At least for the floating-point support, it looks like you specify the number of bits to use: http://www.mpfr.org/sample.html – Ben Voigt Feb 24 '15 at 00:14
  • 1
    The answer is missing the "smaller than a byte" aspect. – milleniumbug Feb 24 '15 at 00:20
  • @SimonOroño Aha; I didn't realize that sub-byte sizes was important to you. – Aasmund Eldhuset Feb 24 '15 at 00:24
  • @SimonOroño if you want fixed width integer/floating-point types then you should use [ttmath](http://www.ttmath.org/faq) or [boost::multiprecision](http://www.boost.org/doc/libs/1_53_0/libs/multiprecision/doc/html/boost_multiprecision/intro.html) – phuclv Feb 24 '15 at 00:30
2

You could write a wrapper class around std::bitset or std::vector<bool>. These are bit containers.

Your class would contain one of the containers and add functionality for conversion to and from integral numbers; as well as other arithmetic operations.

This will allow you to have unusual bit sized integers, such as 3, 5 and 13.

Most implementations will round up to the nearest multiple of 8 or the processor's word size. A container of 3 bits would use a uint8_t with 5 unused bits, primary because its easier for the processor to manipulate. A 13-bit integer would reside in a 16-bit package.

Edit 1: Floating Point Number
Unless you conform to the standard floating point formats, you will have to write your own wrapper class. This would allow you to have 3 bits of mantissa, 5 bits of exponent and one bit for sign -- 9bits. Again, think about all the methods you would need to write. Most applications will use either double or float because there is no need to write separate wrappers which takes coding time and testing time.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • Wrapping around `bitset` or `vector` will be needlessly slow and complicated. Bitsets don't even support dynamic size, it has to be known at compile time. – dtech Feb 24 '15 at 01:00
  • Custom bit sized variables will be needlessly slow and complicated because of the bit set, clear, extraction and packing. The `bitset` or `vector` are convenient containers. – Thomas Matthews Feb 24 '15 at 01:30
  • Depending on the requirements, you could get away with using a tremendously more efficient container than single bit based. – dtech Feb 24 '15 at 01:33
  • Why is a bit container slower? what would be more efficient? @ddriver – Simón Oroño Feb 24 '15 at 11:53
  • @SimonOroño - because you have access overhead for each bit. For a 3bit integer you will have 3 bit accesses, whereas if you store those in an 8, 16, 32 or 64bit integer, you can get the 3bit integer in one operation. Same thing goes for wider than 64bit integers, there the overhead of a bit container will be even more pronounced, it will be far more efficient to represent the number using the standard primitive integers - and avoid all the masking and shifting which bit access requires altogether. Consider a 128bit integer - that's just two 64bit operations in contrast to 128 1bit operations. – dtech Feb 24 '15 at 12:03
  • 1
    And ironically, on modern hardware operations on 64bit integer operations usually take a single clock cycle, whereas bit access requires 2-3 cycles for the access alone and you still have the actual operation to go. Computers can address a byte at least, so going below byte always has overhead of the bitwise operations needed to extract the value. – dtech Feb 24 '15 at 12:07
1

Explanation:


You could always try to use integer and float manipulation using arrays. If the number is too big for array initialization, you could use the malloc(); function.

Please Note: This method is not very fast, because we will be allocating memory in the heap. You will also have to write your own mathematical operation functions, because I am not quite sure on how to implement it efficiently. SEE MORE BELOW


How to implement (sort of):


#include <stdio.h>
#include <stdlib.h>

#define MAX_DIGIT_COUNT 1000

int main()
{
    int* big_num = (int*)malloc(sizeof(int) * MAX_DIGIT_COUNT); //allocate memory
    for(int x; x<MAX_DIGIT_COUNT; x++)
    {
        /*
        *Iterating through number - iterating works, because we are basing out max number lenght 
        *off of the maximum digits, and therefore, we can have a maximum of 2^64 digits
        */
        big_num[x] = rand()%5; //fill up memory block with psuedo-random numbers
    }
    /*Printing begins here...*/
    for(int i; i<MAX_DIGIT_COUNT; i++)
    {
        int iterated;
        iterated = big_num[i];
        printf("%d", iterated);
    }
    printf("\n");
    /*Printing ends here*/
    return 0;
}

Please note: This is just a crude way of implementing arbitrary-sized number support in pure C.

  • By the way, you could use `char arrays` to improve memory efficiency... –  Feb 08 '18 at 05:13
-2

No, size of every primitive element (int,short,long...) depends of hardware architecture.

For bigger sizes, you should use one Big Integer library (they represent numbers with strings).

amchacon
  • 1,891
  • 1
  • 18
  • 29
  • Could you elaborate on what you mean by "strings"? – Neil Kirk Feb 23 '15 at 23:57
  • Example: "94314". Strings can have one arbitrary size, so you can have bigger numbers. – amchacon Feb 24 '15 at 00:00
  • 1
    The problem is redefine arithmethics operations. @NeilKirk – amchacon Feb 24 '15 at 00:00
  • Why not represent an arbitrary integer with an array of ints of certain size? That will be much faster than a text string. – Neil Kirk Feb 24 '15 at 00:13
  • 1
    "No, size of every primitive element (int,short,long...) depends of hardware architecture." Hmmm - With the same hardware platform, I can use various compilers and option settings and have control on the range of `char` (sign or unsigned), `int` (16 or 32), `long` (32 or 64 bit). I'd say the compiler has ultimate control. and not the hardware. – chux - Reinstate Monica Feb 24 '15 at 01:01