Skip to content

Numeric overflow and conversion

SyntaxDescriptionNote
int.MaxValue + 1int overflowNo exception is raised.
long.MaxValue + 1long overflow
(uint)0 - 1Unsigned overflow
unchecked { n = n + 1; }Wrap in uncheckedBecause it was never being checked.
(byte)300Narrowing conversion
(int)2.7fFloat-to-int conversion
byte + byteArithmetic between small types
-7 / 2Integer division
1f / 0fDivide a float by 0
0.1 + 0.2Floating-point errorThe result is the same as in C#.
SyntaxDescriptionErrorReasonAlternative
checked { n = n + 1; }Halting when a value overflowsTUKI0001by designCheck with an if that the result fits in range before computing. unchecked does compile
When it is knownWhether a value overflows is decided by the runtime value, so it cannot be known at compile time
uncheckedIt compiles. Nothing was being checked to begin with, so wrapping code in it does not change the value

Going past the maximum wraps to the minimum, and below the minimum wraps to the maximum.

using UnityEngine;
using Tsukimi;
public class NumericsIntOverflow : TsukimiBehaviour
{
void Start()
{
int max = int.MaxValue;
max = max + 1;
Debug.Log(max); // => -2147483648
int min = int.MinValue;
min = min - 1;
Debug.Log(min); // => 2147483647
}
}
using UnityEngine;
using Tsukimi;
public class NumericsLongOverflow : TsukimiBehaviour
{
void Start()
{
long n = long.MaxValue;
n = n + 1;
Debug.Log(n); // => -9223372036854775808
}
}
using UnityEngine;
using Tsukimi;
public class NumericsUnsignedWrap : TsukimiBehaviour
{
void Start()
{
uint n = 0;
n = n - 1;
Debug.Log(n); // => 4294967295
}
}

Wrapping it in unchecked gives the same value as leaving it out.

using UnityEngine;
using Tsukimi;
public class NumericsUncheckedOverflow : TsukimiBehaviour
{
void Start()
{
int n = int.MaxValue;
unchecked { n = n + 1; }
Debug.Log(n); // => -2147483648
}
}
using UnityEngine;
using Tsukimi;
public class NumericsNarrowingCast : TsukimiBehaviour
{
void Start()
{
int over = 300;
Debug.Log((byte)over); // => 44
int negative = -1;
Debug.Log((byte)negative); // => 255
}
}
using UnityEngine;
using Tsukimi;
public class NumericsFloatTruncation : TsukimiBehaviour
{
void Start()
{
float positive = 2.7f;
Debug.Log((int)positive); // => 2
float negative = -2.7f;
Debug.Log((int)negative); // => -2
}
}
using UnityEngine;
using Tsukimi;
public class NumericsSmallTypeArithmetic : TsukimiBehaviour
{
void Start()
{
byte a = 200;
byte b = 200;
int sum = a + b;
Debug.Log(sum); // => 400
short s = 30000;
short t = 30000;
int total = s + t;
Debug.Log(total); // => 60000
}
}
using UnityEngine;
using Tsukimi;
public class NumericsIntegerDivision : TsukimiBehaviour
{
void Start()
{
int n = -7;
Debug.Log(n / 2); // => -3
Debug.Log(n % 2); // => -1
}
}

Dividing an integer by 0 halts execution, but a float gives Infinity.

using UnityEngine;
using Tsukimi;
public class NumericsFloatDivideByZero : TsukimiBehaviour
{
void Start()
{
float one = 1f;
float zero = 0f;
Debug.Log(one / zero); // => Infinity
}
}

Some values can’t be represented as binary fractions, so you don’t get exactly the value you wrote in decimal.

using UnityEngine;
using Tsukimi;
public class NumericsDoublePrecision : TsukimiBehaviour
{
void Start()
{
double sum = 0.1 + 0.2;
Debug.Log(sum); // => 0.30000000000000004
}
}