1

I noticed something in my visual studio (2017) and was hoping to get some help.

I have a very small representation of a second (nanoseconds, 1.0e-9) but also a large representation of seconds (>3e10) that have passed, but when adding the two numbers together the nanoseconds disappears or is wrong.

For example:

double nanosecond = 1.0e-9;
double seconds_in_year = 31536000.0;
double result = seconds_in_year + nanosecond;

What I get for result is seconds_in_year, with no 1.0e-9. If I change nanosecond to ~5.0e-9, I get 31536000.000000004, which is off by one nanosecond.

It seems I can add very small numbers together (nano + nano) or large numbers, but when trying to combine the two it starts to go wrong. Any advice on how to work around this? I am using c++11, and cannot use external libraries like boost.

EDIT: I have gotten some comments and flags saying its a duplicate, but as far as I can see none of the suggestions actually offer a solution (unless I missed it). I get the computer can only handle so many bits or digits of precision

So to rephrase my question: How can I in C++ do proper arithmetic on very small and very large numbers. Create an class/object?

user2840470
  • 919
  • 1
  • 11
  • 23
  • 2
    Everything you need is at [What Every Computer Scientist Should Know About Floating-Point Arithmetic](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – selbie Oct 01 '17 at 16:43
  • 1
    double doesn't have that large precision. It can be precise to only ~15-17 digits – phuclv Oct 01 '17 at 16:49
  • [Why does adding a small float to a large float just drop the small one?](https://stackoverflow.com/q/22186589/995714) – phuclv Oct 01 '17 at 16:51
  • 1
    I don't know whether a ready solution exists or not. Don't use floating point for this. I'd use a 64-bit integer counting nanoseconds. This way you can store nanoseconds precision time, largest time being is ~290 years (signed) – geza Oct 01 '17 at 19:24
  • Try searching for `c++ arbitrary precision floating point`. – HABO Oct 01 '17 at 20:07
  • @geza 3e10 seconds are about 900+ years if I didn't do any typo in calculator, so he needs even more than 64 bit integer. OP: sounds very weird to need both nanoseconds and thousands of years range, covered by the same variables. Can you shed some light what you are actually trying to achieve? Your platform+compiler [**may** support __int128_t](https://stackoverflow.com/a/35026162/4271923) type, that would give you another few millions+ of years of range available. ... but certainly avoid floating point types, if you need this kind of precision. – Ped7g Oct 02 '17 at 05:27
  • @Ped7g: why do you calculate with 3e10 seconds? Unsigned: 2^64=1.8e19. Signed: 2^63: 9e18. (I've calculated with signed). – geza Oct 02 '17 at 10:29
  • @geza *"but also a large representation of seconds (>3e10) that have passed"* (from question) – Ped7g Oct 02 '17 at 10:45
  • @Ped7g: ah, okay then, sorry :) – geza Oct 02 '17 at 10:47
  • 1
    you may want to decrease your requirements just a little bit, so it fits into 64-bit. If you don't use time for some serious computation (physics simulation, whatever), you may not want to use nanosecond resolution. For example, my Time class uses 24 bits for subsecond precision. This is more than enough for almost anything, and can store ~17000 years. – geza Oct 02 '17 at 10:52

0 Answers0