LogicGates.org Open the simulatorSimulator

int16: the 16-bit signed integer

int16 holds every whole number from −32,768 to 32,767, which is −2¹⁵ to 2¹⁵ − 1. That is 2¹⁶ = 65,536 values in 16 bits, stored in two’s complement.

int16 limits

Maximum
32,767
power2¹⁵ − 1
hex0x7FFF
binary0111 1111 1111 1111
Minimum
−32,768
power−2¹⁵
hex0x8000
binary1000 0000 0000 0000
Distinct values
2¹⁶ = 65,536
Size
16 bits, 2 bytes

The hex and binary forms are the bit patterns. The top bit is the sign: 0 for the maximum, 1 for the minimum.

int16 overflow playground

Starts at the maximum, one step from overflowing. Change the operation, the value or the type, or cast to another width, and watch the bits wrap.

Decimal, 0x hex or 0b binary, with a minus sign if negative. 2^31 − 1 works too.

int16: 32,767 +1 −32,768 Overflow: wrapped past the maximum to the bottom of the range
Before 0x7FFF
Exact answer 32,768 written in 17 bits: the leftmost bit does not fit and is dropped
After 0x8000

The solid underlined bit is the sign bit: 1 means negative in a signed type. Struck-through bits are dropped.

  1. Exact answer: 32,768.
  2. That is above the maximum of int16, 32,767.
  3. The hardware keeps only the low 16 bits, which is the same as taking the answer modulo 2¹⁶ = 65,536: 32,768.
  4. The top bit is 1, so read as signed it is 32,768 − 65,536 = −32,768.

What int16 is called in each language

Language Type Limits in code Note
C and C++ int16_t INT16_MIN, INT16_MAX short is at least 16 bits, and exactly 16 on common platforms.
Java short Short.MIN_VALUE, Short.MAX_VALUE
C# short short.MinValue, short.MaxValue
Rust i16 i16::MIN, i16::MAX
Go int16 math.MinInt16, math.MaxInt16
Swift Int16 Int16.min, Int16.max
Kotlin Short Short.MIN_VALUE, Short.MAX_VALUE
MySQL SMALLINT
PostgreSQL smallint (int2)
SQL Server smallint
JavaScript Int16Array element
Python ctypes.c_int16

Only names with exactly 16 bits on every platform are listed as the type.

What happens when int16 overflows

In 16 bits, 32,767 + 1 wraps to −32,768, and −32,768 − 1 wraps to 32,767. The processor keeps the low 16 bits of the answer, which is the same as working modulo 2¹⁶, and the top bit then decides the sign. You can see it in JavaScript:

new Int16Array([32767 + 1])[0] → -32768

Whether a program is allowed to wrap like that depends on the language:

What each language does when integer arithmetic overflows
Language By default To check or wrap on purpose
C and C++ Unsigned types wrap around modulo 2ⁿ. Signed overflow is undefined behaviour: the compiler may assume it never happens and optimise on that basis. Types narrower than int are promoted to int first, so even uint16_t × uint16_t can overflow a signed int. __builtin_add_overflow (GCC, Clang); ckd_add in C23’s <stdckdint.h>; -fsanitize=undefined to catch it
Java Wraps around silently, in two’s complement. Math.addExact, multiplyExact and friends throw ArithmeticException
C# Wraps around, unless the code is in a checked context, which throws OverflowException. A constant expression that overflows is a compile error. checked(...) blocks, or the CheckForOverflowUnderflow compiler option
Rust Panics in debug builds. Release builds wrap, unless overflow-checks is turned on for that profile. checked_add, wrapping_add, saturating_add, overflowing_add
Go Wraps around silently. Only constant expressions that overflow are compile errors. math/bits.Add64 reports the carry; Mul64 returns the high half of the product
Swift Traps: the program stops with a runtime error. &+, &-, &* wrap on purpose; addingReportingOverflow reports it
Kotlin Wraps around silently, like Java. Math.addExact on the JVM
JavaScript Numbers never wrap, but lose precision past 2⁵³. Bitwise operators and typed arrays wrap to their width. BigInt never overflows. Number.isSafeInteger; BigInt.asIntN and asUintN to wrap deliberately
Python int never overflows: it grows as needed. ctypes and NumPy fixed-width types do wrap
SQL An error: the statement fails with an out of range or arithmetic overflow message. MySQL outside strict mode clips an out-of-range value stored into a column to the limit, with a warning

In C and C++, arithmetic on 16-bit types is done in int, so the sum itself does not overflow; it wraps when stored back into the int16_t. That conversion is implementation defined in C (GCC and Clang wrap) and defined as wrapping since C++20.

Common mistakes with int16

  • Negating −32,768 or taking its absolute value. The exact answer, 32,768, is one past the maximum of 32,767, so once it is stored as int16 it wraps back to −32,768: −x and abs(x) of the minimum stay negative.
  • Expecting short arithmetic in Java to stay short. s = s + 1 does not compile when s is a short, because s + 1 is an int. s += 1 and s++ do compile, and silently wrap 32,767 to −32,768.

When int16 overflowed for real

Ariane 5 flight 501

On 4 June 1996 the first Ariane 5 broke up about 40 seconds after lift-off. Its inertial reference software converted a 64-bit floating-point value, the horizontal bias, into a 16-bit signed integer. The value was larger than 32,767, the conversion raised an exception, both inertial reference units shut down, and the rocket veered off course and was destroyed.

Where you meet int16

  • CD audio and most WAV files: 16-bit signed samples
  • Older and embedded systems where int is 16 bits

Need no negatives and twice the reach? The unsigned type of the same width is uint16, from 0 to 65,535.

Every integer type

Type Minimum Maximum
int8 −128 127
uint8 0 255
int16 this page −32,768 32,767
uint16 0 65,535
int32 −2,147,483,648 2,147,483,647
uint32 0 4,294,967,295
int64 −9,223,372,036,854,775,808 9,223,372,036,854,775,807
uint64 0 18,446,744,073,709,551,615
int128 −170,141,183,460,469,231,731,687,303,715,884,105,728 170,141,183,460,469,231,731,687,303,715,884,105,727
uint128 0 340,282,366,920,938,463,463,374,607,431,768,211,455

Questions

What is the maximum value of int16?

32,767, which is 2¹⁵ − 1 or 0x7FFF in hex. The minimum is −32,768 (−2¹⁵).

Why is the minimum of int16 one further from zero than the maximum?

16 bits make 2¹⁶ patterns. Two’s complement gives the half with the top bit set to the negatives, −32,768 to −1, and the other half to zero and the positives, 0 to 32,767. Zero takes one of the non-negative patterns, so there is one more negative number than positive. That is also why negating −32,768 overflows back to itself.

How many values can int16 hold?

2¹⁶ = 65,536 distinct values, from −32,768 to 32,767.

What happens when int16 overflows?

On the hardware the result keeps only its low 16 bits, so 32,767 + 1 becomes −32,768. In C, C++, Java, C# and Kotlin, arithmetic on 16-bit values is done in int, so 32,767 + 1 is 32,768 as an int; it becomes −32,768 only when stored back into the 16-bit type, as x++, a cast or (except in Kotlin, where it does not compile) x += 1 do. Go wraps at 16 bits directly, Rust panics in debug builds and wraps in release builds, and Swift stops with a runtime error.

What is int16 called in other languages?

C and C++: int16_t; Java: short; C#: short; Rust: i16; Go: int16; Swift: Int16; Kotlin: Short; Python: ctypes.c_int16. In SQL: SMALLINT in MySQL, smallint (int2) in PostgreSQL, smallint in SQL Server.