13

I have an integer variable, that can get a value larger than 4294967295.

What type should I use for it (long long, or double, or something else)?

Igor
  • 26,650
  • 27
  • 89
  • 114
  • 1
    an could it be extraordinarily larger? because people are dwelling over issues of 64bits, but if you tell them you're looking at astronomical distances, or atoms count, the answer quickly shifts to "double", forget integers. – jpinto3912 Jun 06 '09 at 10:21
  • Great comment! In my case it doesn't get larger than 64bit, but it is still interesting, what to do if it does? Why should I use "double" in such case? – Igor Jun 06 '09 at 10:31

14 Answers14

14

Use long long and if possible add a compile-time assertion that this type is wide enough (smth like sizeof( long long ) >= 8).

double is for floating-point, not integer.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 9
    long long is not a standard C++ data type –  Jun 01 '09 at 11:09
  • 6
    According to ISO/IEC 9899:TC3 - Committee Draft — Septermber 7, 2007 - Major changes from the previous edition include: the long long int type and library functions maximum value for an object of type long long int LLONG_MAX 9223372036854775807 (2^63 - 1) –  Jun 01 '09 at 11:45
  • 4
    That is a C99 document, not C++. –  Jun 01 '09 at 12:33
  • 1
    @Neil: +1 I always thought it was the same in C++, but it seems it is not. According to Working Draft, Standard for Programming Language C++ (N2798=08-0308): There are five standard signed integer types : “signed char”, “short int”, “int”, “long int”, and “long long int”. In this list, each type provides at least as much storage as those preceding it in the list. –  Jun 01 '09 at 13:16
  • 1
    Note the N2798 document you quote from is the unratified C++0x draft - standard C++ does not yest have long long integers. –  Jun 01 '09 at 13:26
  • 1
    long long works with g++, so if you happen to use that it's OK and it will be supported in C++0x, too. – lothar Jun 01 '09 at 15:14
13

Try:

http://gmplib.org/ big num.

http://mattmccutchen.net/bigint/ big int.

I've used neither, but I've used similiar things in Java.

Pod
  • 3,938
  • 2
  • 37
  • 45
9

I'm going to assume your numbers will fit in 64 bits. If not, then you need an arbitrary-precision arithmetic library such as GMP.

In theory, there's no easy, portable way to do 64-bit maths in C++. In practise, most C++ compilers also support the "old fashioned" C headers, and C99 has a nice header called stdint.h.

So first do:

#include <stdint.h>

Then use types int64_t (signed) and uint64_t (unsigned).

EDIT TO ADD: After I wrote this answer, C++11 added the <cstdint> header which normally* defines std::int64_t and std::uint64_t , so if you have a modern compiler it's best to use those.

(* In theory the system might not support a 64-bit type at all. But in practise it will, on any system you're likely to come across).

user9876
  • 10,954
  • 6
  • 44
  • 66
7

There is no portable way of doing this in C++, as the language does not specify the size of integer types (except sizeof char is 1). You need to consult your compiler documentation.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 5
    Not quite true. The standard does specify the minimum magnitudes of each type and thus by implication a minimum bit (not byte) count see http://stackoverflow.com/questions/271076/what-is-the-difference-between-an-int-and-a-long-in-c/271132#271132 – Martin York Jun 01 '09 at 15:20
  • 1
    Since C++11 there are `long long` and `unsigned long long` types which are guaranteed to be at least 64 bit wide and their respective `ll`, `ull` literals. Also in `cstdint` header there are `int64_t`, `int_least64_t`, `int_fast64_t`, `uint64_t`, `uint_least64_t`, `uint_fast64_t` type aliases available. –  May 24 '16 at 04:56
3

Both proposals aren't good because long long is not a standard C++ data type, and double is a floating-point.

Since my program has to be portable, I am going to #define my own types, that suit all the compilers that I use (visual studio and gcc) :

#ifdef WIN32
  #define unsigned_long_long unsigned __int64
  #define long_long __int64
#else // gcc. Might not work on other compilers!
  #define unsigned_long_long unsigned long long
  #define long_long long long
#endif
Igor
  • 26,650
  • 27
  • 89
  • 114
  • 1
    Note this is not a Windows issue, it is a C++ standards issue - there is no guaranteed that non-windows platforms will support long long. –  Jun 01 '09 at 11:31
  • According to MSDN long long is equivalent to __int64 in VC++ and so you don't need that define. – sharptooth Jun 01 '09 at 11:32
  • Also note that g++ will emit lots of warnings if compiled with -pedantic, which I think most C++ programs are (they certainly should be) –  Jun 01 '09 at 11:38
  • Neil: Why would it emit warnings? – Igor Jun 01 '09 at 11:51
  • Because long long is not standard C++ - it is part of C99, which g++ supports. Using -pedantic to compile C++ code will give aq warning about this. –  Jun 01 '09 at 12:35
  • If you really want to go that way, you would be better off using a portable library (ACE comes to mind) that provides 64 bit integers (ACE_INT64, ACE_UINT64) across platforms and operating systems. It is non-standard (detects the platform/compiler and uses your own type of hacks) but will work on other systems. – David Rodríguez - dribeas Jun 01 '09 at 14:48
3

Don't use double, because:

cout.setf(ios::fixed);
cout << LONG_LONG_MAX << endl;
cout << double(LONG_LONG_MAX) << endl;

cout << LONG_LONG_MAX-100 << endl;
cout << double(LONG_LONG_MAX-100) << endl;

Output:

9223372036854775807
9223372036854775808.000000
9223372036854775707
9223372036854775808.000000
2

I use

uint64_t

But it's not standard.

  • 1
    Actually stdint.h is part of C99. But many compiler vendors are relucent in supporting "new" standard even after 10 years (anyone remembers how IT looked like 10 years ago?!). – lispmachine Jun 01 '09 at 12:36
  • I don't know about your work, but for me, only three compiler vendors matter. Microsoft, Intel, and GCC. And all three have traditionally been good at "new" standard compliance. Not so much SunW C++ or HP or IBM, but in the Windows/Linux world, it should be a non-issue. 15 years ago, I remember breaking compilers and linkers for breakfast. In fact, it took DEC the better part of two months to fix a linker bug so we could ship Pro/ENGINEER for WindowsNT Alpha, back in the days when 32 MB executables where unheard of. – Chris K Jun 01 '09 at 14:11
1

if you don't need negative numbers, unsigned long long sounds like most you can get.

Slartibartfast
  • 8,735
  • 6
  • 41
  • 45
1

Try TTMath. All you need to do is include a single header and then declare a bignum type such as:

typedef ttmath::UInt<100> BigInt;

which creates a type that can hold unsigned integers between 0 and 2 ^ (32*100)-1. Then just use BigInt wherever you would use int.

Of course you can choose whatever size you like for the template parameter. 100 might be overkill ;-)

Just realised, the lib only works on x86 and x64, but is OS cross-platform on those processors.

PowerApp101
  • 1,798
  • 1
  • 18
  • 25
  • i'm stuck trying to use ttmath and used what you said. you said he would need to use BigInt on the place where he would use Int but the facts is that i get this error "class BigInt has no member called ...", why do you think this is happening? – wxiiir Nov 16 '11 at 18:00
  • @wxiir You said in your other post that you were getting an error saying `BigInt has no member named blah` when your variable was named `blah` (that shouldn't happen). What happens you try a simple declaration like `ttmath::UInt<100> blah = 0; blah = blah + 10;`? – HostileFork says dont trust SE Nov 16 '11 at 18:32
1

A lot of current C/C++ compilers have either stdint.h or inttypes.h header.

int_fast64_t or int64_t may be an option (IMHO the most portable).

lispmachine
  • 4,407
  • 1
  • 22
  • 31
1

How portable should your program be? TR1 has cstdint and stdint.h so it's likely supported by most up-to-date compilers. Then there is Boost cstdint.hpp that you should be able to use if cstdint is not supported.

TrayMan
  • 7,180
  • 3
  • 24
  • 33
0

Just out of curiosity - I don't think it would be too hard to code your own if you wanted to. I mean, all of these data types have predefined structures, of course, but you could, for example, use the double structure which uses exponents, and do something like this:

to hold a VERY large number, beyond the scale of a double, create an object that has two parts to it - the number and the power to ten,

so, if you wanted to store something like

1.1230123123 x 10^(100000000000000000000000000000000000), which isn't supported by a double, you could have the 1.123 ... part stored in a double, and then the power of ten as a seperate double/int/float (whatever suits), and then take it from there. Of course, this may not be the best way - and you would probably have to code in a lot of functionality for division, subtraction etc, but it would definitely by portable, as you would be using the normal data types defined. The useability of this would depend on what you are trying to achieve and whether or not you plan to use this beyond a single project, but I think it is a liable way to do it if those sorts of numbers are an absolute requirement

Sbspider
  • 389
  • 5
  • 14
0

Doubles are floating-point. You should use long long, probably. I don't know which alias is the preferred one.

alamar
  • 18,729
  • 4
  • 64
  • 97
0

If your compiler does not have long long you can implement them yourself with a structure containing two long but you will need to be caurseful with carry etc. You could of course look for a Multiple Precision Arithmetic like GMP

David Allan Finch
  • 1,414
  • 8
  • 20