Skip to content

Numbers

SyntaxDescription
int.MaxValue + 1int overflow
long.MaxValue + 1long overflow
(uint)0 - 1Unsigned overflow
unchecked { n = n + 1; }Wrap in unchecked
(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 error

Forms that compile with different values (2)

Section titled “Forms that compile with different values (2)”

No error occurs. It compiles and runs. But there are conditions where the value differs from regular C#.

SyntaxWhat happens
checked { n = n + 1; }In C#, an exception is thrown at the point of overflow and execution stops. Here nothing happens, and execution continues with the overflowed value
(int)1e10fIn C#, this becomes the minimum value of int. Here execution stops, and nothing after it runs
using UnityEngine;
using Tsukimi;
public class SilentCheckedOverflow : TsukimiBehaviour
{
void Start()
{
int n = int.MaxValue;
checked { n = n + 1; }
Debug.Log(n);
}
}
using UnityEngine;
using Tsukimi;
public class SilentFloatToIntOutOfRange : TsukimiBehaviour
{
void Start()
{
float huge = 1e10f;
Debug.Log((int)huge);
}
}

Both are determined by the runtime value, so they can’t be known at compile time. checked in particular has no effect, since there’s no exception mechanism.

Going above the upper bound wraps to the lower bound, and going below the lower bound wraps to the upper bound. No exception occurs.

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 in unchecked gives the same value as not wrapping it. It wasn’t checking to begin with.

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 stops execution, but for a float it becomes 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 exactly in binary floating point, so the result doesn’t match what’s written in decimal. The result is the same as C#.

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