C# has the predefined numeric types.
There are three types of predefined numeric types:
Predefined Integral-signed numeric types in C#:
C# type | System type | Suffix | Size | Range |
---|---|---|---|---|
sbyte | SByte | No Suffix | 8 bits | -2^7 to 2^7 -1 |
short | Int16 | No Suffix | 16 bits | -2^15 to 2^15-1 |
int | Int32 | No Suffix | 32 bits | -2^31 to 2^31-1 |
long | Int64 | L | 64 bits | -2^63 to 2^63-1 |
Predefined Integral-unsigned numeric types in C#:
C# type | System type | Suffix | Size | Range |
---|---|---|---|---|
byte | Byte | No Suffix | 8 bits | 0 to 2^8 -1 |
ushort | UInt16 | No Suffix | 16 bits | 0 to 2^16-1 |
uint | UInt32 | U | 32 bits | 0 to 2^32-1 |
ulong | UInt64 | UL | 64 bits | 0 to 2^64-1 |
Predefined real numeric types in C#:
C# type | System type | Suffix | Size | Range |
float | Single | F | 32 bits | +/- (~10^-45 to 10^38) |
double | Double | D | 64 bits | +/- (~10^-324 to 10^308) |
decimal | Decimal | M | 128 bits | +/- (~10^-28 to 10^28) |
The decimal type is typically used for financial calculations.
Integral literals can use decimal or hexadecimal notation.
Hexadecimal is denoted with the 0x
prefix.
For example:
int x = 17;
long y = 0x8F;
Real literals can use decimal and/or exponential notation.
For example:
double d = 1.5;
double million = 1E06;
*** You can insert an underscore anywhere inside a numeric literal to make it more readable:
int million = 1_000_000;
*** You can specify numbers in binary with the 0b
prefix:
var b = 0b1010_1001_1110_1101_1010_1101;
Example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
int x = 127;
long y = 0x7F;
Console.WriteLine(x);
Console.WriteLine(y);
double d = 1.5;
double million = 1E06;
Console.WriteLine(d);
Console.WriteLine(million);
Console.ReadLine();
}
}
}
Output:
C# compiler infers a numeric literal to be either double or an integral type:
int
, uint
, long
, and ulong
.For example:
double
by default since it has decimal part.int
type.The following code outputs the inferred type for each literal:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(1.0.GetType()); // (double)
Console.WriteLine(1E06.GetType()); // Double (double)
Console.WriteLine(1.GetType()); // Int32 (int)
Console.WriteLine(0xF0000000.GetType()); // UInt32 (uint)
Console.WriteLine(0x100000000.GetType()); // Int64 (long)
Console.ReadLine();
}
}
}
Output:
Numeric suffixes explicitly define the type of a literal.
You can set a literal type by using suffix.
By default 1.0 is inferred as double
by C# compiler, if you want to make it float type, you can add F
as suffix.
Suffixes can be either lower or uppercase. and are as follows:
Category | C# type | Example |
---|---|---|
F | float | float f = 1.0F; |
D | double | double d = 1D; |
M | decimal | decimal d = 1.0M; |
U | uint | uint i = 1U; |
L | long | long i = 1L; |
UL | ulong | ulong i = 1UL; |
F
and M
suffixes are the most useful and should always be applied when specifying float or decimal literals.
Without the F
suffix, the following line would not compile, because 4.5 would be inferred to be of type double
, which has no implicit conversion to float
:
float f = 4.5F;
The same principle is applied for a decimal literal:
decimal d = -1231.13M; // Will not compile without the M suffix.
Example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(1.0.GetType()); // (double)
Console.WriteLine(1E06.GetType()); // Double (double)
Console.WriteLine(1.GetType()); // Int32 (int)
Console.WriteLine(0xF0000000.GetType()); // UInt32 (uint)
Console.WriteLine(0x100000000.GetType()); // Int64 (long)
Console.WriteLine(1.0F.GetType());
Console.WriteLine(1E06F.GetType());
Console.WriteLine(1U.GetType());
Console.ReadLine();
}
}
}
Output:
Converting between integral types:
Integral type conversions are implicit if the destination type can represent every possible value of the source type.
Otherwise, an explicit conversion is required.
For example:
int x = 1; // int is a 32-bit integer
long y = x; // Implicit conversion to 64-bit integral type
short z = (short)x; // Explicit conversion to 16-bit integral type
A double
can represent every possible value of a float
.
A float
point value can be implicitly converted to a double
.
Assign double
type to float
type must be explicit.
All integral types may be implicitly converted to all floating-point types:
int i = 5;
float f = i;
The reverse conversion must be explicit:
int i2 = (int)f;
*** When you cast from a floating-point number to an integral, any fractional portion is truncated(lost).
Note:
System.Convert
has methods to round floating point values while converting between various numeric types.Example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
int i1 = 100000001;
float f = i1; // Magnitude preserved, precision lost
int i2 = (int)f;
Console.WriteLine(i1);
Console.WriteLine(f);
Console.WriteLine(i2);
Console.ReadLine();
}
}
}
Output:
A decimal value can represent every possible integral-type value in C#.
All integral types can be implicitly converted to the decimal type.
All other numeric conversions to and from a decimal type must be explicit.
C# provides the following built-in type conversion methods:
The following example converts various value types to string type:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
int i = 75;
float f = 53.005f;
double d = 2345.7652;
bool b = true;
Console.WriteLine(i.ToString());
Console.WriteLine(f.ToString());
Console.WriteLine(d.ToString());
Console.WriteLine(b.ToString());
Console.ReadLine();
}
}
}
Output: