1

I'd like to assign a value to a variable like this:

double var = 0xFFFFFFFF;

As a result var gets the value 65535.0 assigned. Since the compiler assumes a 64bit target system the number literal (i.e. all respective 32 bits) is interpreted significand precision bits. However, since 0xFFFF FFFF is just a notation for a bit pattern, without any hint about the representation, it could be quite differently interpreted w.r.t. becoming a floating point value. Thus, I was wondering if there is a way to manipulate this fixed interpretation of the value. In other words, give a hint about the desired representation. (Maybe someone could also point me to part in the standard where this implicit interpretation is defined).

So far, the default precision interpretation on my system seems to be

(int)0xFFFFFFFF x 100.

enter image description here Only the fraction field is getting filled1.

So maybe (here: for 16 bit cross-compilation) I want it to be a different representation like:

(int)0xFFFFFF x 10(int)0xFF

(ignoring the sign bit for a moment).

Thus my question: How can I force a custom double interpretation of the hex literal notation?


1 Even when my hex literal would be 0xFFFF FFFF FFFF FFFF the value is only interpreted as the fraction part - so clearly, bits should be used for exponent and sign field. But it seems the literal gets just cut off.

Jim McAdams
  • 1,034
  • 1
  • 14
  • 30
  • 3
    And what is your real question (XY-problem) ? –  Jun 25 '15 at 19:51
  • 1
    0xffff is the same as 65535. – molbdnilo Jun 25 '15 at 19:53
  • @[Dieter Lücking](http://stackoverflow.com/users/2249683/dieter-l%c3%bccking) See update: How can I force double interpretation of the hex notation? – Jim McAdams Jun 25 '15 at 19:53
  • 1
    `How can I force double interpretation of the hex notation` What's wrong with just saying `double var = 65535.0;` – PaulMcKenzie Jun 25 '15 at 19:53
  • It's a duplicate of this question: http://stackoverflow.com/questions/8521638/exact-binary-representation-of-a-double – Ivan Mushketyk Jun 25 '15 at 19:54
  • @[molbdnilo](http://stackoverflow.com/users/404970/molbdnilo) No that's what I'm trying to avoid and that's what seems to be the default standard. – Jim McAdams Jun 25 '15 at 19:54
  • @Kris this doesn't compile – Anton Savin Jun 25 '15 at 20:01
  • 3
    @JimMcAdams Writing 0xffff is literally the same as writing 65535. The notation makes no difference. – molbdnilo Jun 25 '15 at 20:01
  • I think you're asking about hexadecimal floating point literals ( http://www.effectiveperlprogramming.com/2015/06/perl-v5-22-adds-hexadecimal-floating-point-literals/ ), which exist in Perl and C99, but I don't know if they're in C++. – Max Lybbert Jun 25 '15 at 20:03
  • 1
    "... since casting won't work for obvious reasons" - with how your question is phrased, those reasons are anything-but-obvious. Dieter's comment holds much weight. What is the *real* problem you're trying to solve? I suspect Ivan's link holds much relevance, but without more specifics from you it is difficult to tell. – WhozCraig Jun 25 '15 at 20:09
  • What is your idea of a floating point interpretation of 0xffff ? – Captain Giraffe Jun 25 '15 at 20:14
  • @[May Lybbert](http://stackoverflow.com/users/10593/max-lybbert) Thanks, that's an interesting article and yes, I'm looking for the respective implementation in C++. ;) – Jim McAdams Jun 27 '15 at 00:51
  • @[WhozCraig](http://stackoverflow.com/users/1322972/whozcraig) What I meant was that the compiler interprets all the bits of `0xFF..` before it is checking on any other conversion wrapped around it. So no matter what I put around it, it will always do its thing first. Seemed obvious for me at least. Hope the question makes now more sense. – Jim McAdams Jun 27 '15 at 00:51
  • @all I read the other linked threads. It seems that the cause of our problems is indeed the same but the resulting questions aren't. So, I'm not really sure if it's a doublicate. Gotta read them again probably. ;P – Jim McAdams Jun 27 '15 at 00:51
  • [c++ portable conversion of long to double](https://stackoverflow.com/q/19843704/995714), [Double from long bits](https://stackoverflow.com/q/17409162/995714) – phuclv Aug 03 '18 at 09:55
  • Possible duplicate of [Portable way to serialize float as 32-bit integer](https://stackoverflow.com/questions/40416682/portable-way-to-serialize-float-as-32-bit-integer) – phuclv Aug 03 '18 at 09:56

3 Answers3

3

"I was wondering if there is a way to manipulate this interpretation."

Yes, you can use a reinterpret_cast<double&> via address, to force type (re-)interpretation from a certain bit pattern in memory.

"Thus my question: How can I force double interpretation of the hex notation?"

You can also use a union, to make it clearer:

union uint64_2_double {
    uint64_t bits;
    double dValue;
};

uint64_2_double x;
x.bits = 0x000000000000FFFF;

std::cout << x.dValue << std::endl;
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
3

There does not seem to be a direct way to initialize a double variable with an hexadecimal pattern, the c-style cast is equivalent to a C++ static_cast and the reinterpret_cast will complain it can't perform the conversion. I will give you two options, one simple solution but that will not initialize directly the variable, and a complicated one. You can do the following:

double var; *reinterpret_cast<long *>(&var) = 0xFFFF;

Note: watch out that I would expect you to want to initialize all 64 bits of the double, your constant 0xFFFF seems small, it gives 3.23786e-319

A literal value that begins with 0x is an hexadecimal number of type unsigned int. You should use the suffix ul to make it a literal of unsigned long, which in most architectures will mean a 64 bit unsigned; or, #include <stdint.h> and do for example uint64_t(0xABCDFE13)

Now for the complicated stuff: In old C++ you can program a function that converts the integral constant to a double, but it won't be constexpr.

In constexpr functions you can't make reinterpret_cast. Then, your only choice to make a constexpr converter to double is to use an union in the middle, for example:

struct longOrDouble {
    union {
        unsigned long asLong;
        double asDouble;
    };
    constexpr longOrDouble(unsigned long v) noexcept: asLong(v) {}
};

constexpr double toDouble(long v) { return longOrDouble(v).asDouble; }

This is a bit complicated, but this answers your question. Now, you can write: double var = toDouble(0xFFFF) And this will insert the given binary pattern into the double.

Using union to write to one member and read from another is undefined behavior in C++, there is an excellent question and excellent answers on this right here: Accessing inactive union member and undefined behavior?

Community
  • 1
  • 1
TheCppZoo
  • 1,219
  • 7
  • 12
3

C++ doesn't specify the in-memory representation for double, moreover, it doesn't even specify the in-memory representation of integer types (and it can really be different on systems with different endings). So if you want to interpret bytes 0xFF, 0xFF as a double, you can do something like:

uint8_t bytes[sizeof(double)] = {0xFF, 0xFF};
double var;
memcpy(&var, bytes, sizeof(double));

Note that using unions or reinterpret_casting pointers is, strictly speaking, undefined behavior, though in practice also works.

Anton Savin
  • 40,838
  • 8
  • 54
  • 90
  • Referring to EdMaster's answer, why is doing this using Unions undefined behavior? – Chuu Jun 25 '15 at 21:01
  • @Chuu because you can't just write to one member of a union and read from another. It's technically UB though works in practice as I said. – Anton Savin Jun 25 '15 at 21:02
  • @Chuu Using unions writing from one side and looking from the other might be undefined behavior, I don't know, but attempting to look at a bit pattern as a `double` is. I think the question was of a practical nature, I am giving practical answers. Undefined behavior or not, to write to one side of the union and look at it from another is a legitimate programming technique, if your platform allows it. I am not sure it is undefined behavior, it might be implementation defined behavior. – TheCppZoo Jun 25 '15 at 21:49
  • 1
    @AntonSavin thanks for pointing out the UB nature of the union. I found an excellent question and also excellent answers on this: http://stackoverflow.com/questions/11373203/accessing-inactive-union-member-undefined – TheCppZoo Jun 25 '15 at 21:56