
Introduction
In daily C++ development, especially when dealing with data that requires a large range of values, such as timestamps and counters, we often use <span>unsigned __int64</span> (also known as <span>uint64_t</span> in the standard library). However, many people may be surprised by the result when they first encounter its subtraction operation.
Let’s look at an example:
#include <iostream>
int main() {
unsigned __int64 a = 134001416236650000;
unsigned __int64 b = 134001416237150000;
auto diff = a - b;
std::cout << "a - b = " << diff << std::endl;
return 0;
}
Program output:
a - b = 18446744073709051616
However, the expected mathematical result should be:
134001416236650000 - 134001416237150000 = -500000
Why is there such a large discrepancy?
1. Rules of Unsigned Integer Operations
The C++ standard specifies:
- • All unsigned integer operations are performed modulo (mod 2^N).
- • For
<span>unsigned __int64</span>, N = 64, so it is mod 2^64.
In other words, <span>unsigned __int64</span> does not represent negative numbers, and all operation results must fall within the range of <span>0 ~ 2^64 - 1</span>.
When <span>a < b</span>, the mathematical result is negative, but <span>unsigned __int64</span> cannot accommodate it, so it wraps around:
a - b = (2^64) - 500000
= 18446744073709551616 - 500000
= 18446744073709051616
This is the “huge value” you see.

2. Incorrect Example: Naively Subtracting Unsigned Values
Many developers directly subtract when calculating time differences:
unsigned __int64 start = getTimestamp();
unsigned __int64 end = getTimestamp();
unsigned __int64 diff = end - start;
If <span>end < start</span> (for example, if the timer resets or crosses an overflow boundary), the result will be completely incorrect.
3. Correct Solutions
It depends on your requirements:
✅ Requirement 1: Want the absolute difference
unsigned __int64 diff = (a > b) ? (a - b) : (b - a);
std::cout << "Absolute diff = " << diff << std::endl;
Output:
Absolute diff = 500000
✅ Requirement 2: Want a signed difference (can represent positive and negative)
__int64 diff = static_cast<__int64>(a) - static_cast<__int64>(b);
std::cout << "Signed diff = " << diff << std::endl;
Output:
Signed diff = -500000
✅ Requirement 3: Timestamp difference function
If you are handling timestamp differences (e.g., microsecond/millisecond level differences), it is recommended to encapsulate a function:
__int64 TimestampDiffMicroSec(unsigned __int64 t1, unsigned __int64 t2) {
return static_cast<__int64>(t1) - static_cast<__int64>(t2);
}
__int64 TimestampDiffMilliSec(unsigned __int64 t1, unsigned __int64 t2) {
return (static_cast<__int64>(t1) - static_cast<__int64>(t2)) / 1000;
}
This way, regardless of whether <span>t1</span> is larger or <span>t2</span> is larger, you can obtain the correct signed difference.
4. Best Practices
- 1. Do not directly perform subtraction on unsigned integers, otherwise, if the order is reversed, the result will wrap around to near 2^64.
- 2. Clarify requirements:
- • If you only need the magnitude of the difference → use the absolute value.
- • If you need the direction of the difference (the order) → use signed integers.
Conclusion
The reason why subtracting two <span>unsigned __int64</span> values does not yield the expected result is not due to a bug in C++, but because the rules of unsigned number operations are modulo 2^64. Negative results under <span>unsigned __int64</span><code><span> will be "wrapped around" to a very large number. The solutions are: for absolute difference → </span><code><span>(a > b) ? (a - b) : (b - a)</span>; for signed difference → convert to <span>__int64</span> and then calculate.
If this article has been helpful to you, I would be very honored.
If you have any other opinions on this article, feel free to leave a comment for discussion.
If you like my articles, thank you for the triple support: like, follow, and share!!!