-1

So I'm wanting to turn an unsigned integer (Fairly large one, often above half of the unsigned integer limit) into a double that shows how far it is between 0 and the unsigned integer limit. Problem is, dividing it by the unsigned integer limit is always returning 0. Example:

#include <iostream>
;
int main()
{
    uint64_t a = 11446744073709551615
    double b = a / 18446744073709551615;
    std::cout << b;
};

This always returns 0. Is there an alternative method or a way to fix this one? If it means anything, I'm using GCC with the -O3 optimisation flag.

R43D43
  • 3
  • 1
  • 1
    The type being assigned to is not considered when an expression is evaluated. You can force floating point onto the expression by e.g. `a / 18446744073709551615 * 1.0`. – 500 - Internal Server Error Apr 11 '22 at 22:41
  • 1
    @500-InternalServerError That won't work either, since it is equivalent to `(a/18446744073709551615)*1.0` (both `*` and `/` have equal precedence, and left-right associativity). It's necessary to force an intermediate result to be promoted BEFORE (not after) doing the division e.g. `1.0 * a / 18446744073709551615` (equivalent to `(1.0 * a)/ 18446744073709551615`) or `a / (18446744073709551615 * 1.0)`. Alternatively do an explicit conversion, rather than relying on implicit promotions (e.g. `static_cast(a) / 18446744073709551615` or `a / static_cast(18446744073709551615)`). – Peter Apr 11 '22 at 23:18

1 Answers1

0

You have to convert the expression on the right to double, for example, like this:

double b = static_cast<double>(a) / 18446744073709551615;

or

double b = a / 18446744073709551615.0;

Alex A.
  • 422
  • 3
  • 12
  • Note that there will be some fuzz. A `double` will run out of precision at about 15 digits, so it can't faithfully represent 18446744073709551615. – user4581301 Apr 11 '22 at 22:47
  • @user4581301 In any case, a certain loss of precision will simply be due to the floating point structure. A 64-bit exact number cannot be losslessly converted to a 64-bit floating point number, since the mantissa of a double is only 53 bits (vs 64 in uint64_t). – Alex A. Apr 11 '22 at 22:52
  • If you need to perform the division as accurately as possible (but why?), then you can implement your own division algorithm. But this is a serious performance hit if you have to do this often. – Alex A. Apr 11 '22 at 22:54
  • @AlexA. "A 64-bit exact number cannot be losslessly converted to a 64-bit floating point number," --> Needs more detail as 0x8000_0000_0000_0000, a 64-bit integer. can be converted exactly to a `double`. – chux - Reinstate Monica Apr 11 '22 at 23:00
  • @chux-ReinstateMonica Or for a simpler example, 0ull is a 64 bit example that can be converted exactly to a double. – eerorika Apr 11 '22 at 23:02
  • "A 64-bit exact number cannot be losslessly converted to a 64-bit floating point number" in a **statistical sense**. That is, yes, there are numbers that can be represented without loss of precision, but there are many numbers that cannot be represented exactly. True and vice versa: double has such large numbers that cannot be put into uint64_t. – Alex A. Apr 11 '22 at 23:07