Negative zero int

380 Views Asked by At

I require a vector of integers, where I can distinguish between 0 and -0. So far i've come up with the idea of defining a new class called zero_int for this special case..

However, now I can't push both normal integers and the zero_int into the same vector. The solution std::variant has the size of 8 Bytes and I need to retain the size of 4 per variable.. Defining a virtual base class my_int and setting zero_int to be its derived class increases the size of zero_int to 32 Bytes...

I'm aware one could use something like a vector<void*> but I don't know how.. - Also, are objects pointed to by the pointers in a vector of pointers contiguous in memory?? - This is important in this case.

I would appreciate any suggestions on how to solve this

2

There are 2 best solutions below

6
Asteroids With Wings On BEST ANSWER

The solution std::variant has the size of 8 Bytes and I need to retain the size of 4 per variable..

That's impossible, unless you don't mind losing one possible non-zero int value.

Which brings us to the "obvious" solution: treat 0 as -0, and every positive number as itself minus one.

    vec[i]:  -5 -4 -3 -2 -1  0 +1 +2 +3 +4 +5
my "value":  -5 -4 -3 -2 -1 -0 +0 +1 +2 +3 +4

(Or do it the other way around, which gives you symmetry in positive and negative ranges; whatever you like.)

Make whatever class wraps your vector handle this "mapping" in whatever way is appropriate for your project.


are objects pointed to by the pointers in a vector of pointers contiguous in memory??

No.

You don't want more indirection here.


Someone will suggest using floating-point, since IEEE 754 supports signed zero. However, I submit that switching to floating-point for representing real numbers in any case is likely to introduce more problems than it solves.

3
Pete Becker On

I'd consider using an unsigned type and explicitly managing the top bit as a sign bit:

class my_int {
public:
    my_int(int v) { set(v); }
    explicit operator int() const { return get(); }
    bool is_negative() const { return value & sign_bit; }
private:
    const static unsigned sign_bit =
        1u << (std::numeric_limits<unsigned>::digits - 1);
    unsigned value;
    void set(int v) { value = v < 0 ? (-v) & sign_bit : v;
    }
    int get() const { return value & sign_bit ? -(value & ~sign_bit) : value; }
};

Caution: written but not tested.