This is just for academic purpose.
I noticed that for integral literals, we can declare up to
18446744073709551615
which is 2^64-1
or ulong.MaxValue
. Defining greater than this value produces a compile-time error.
And for floating-point literals, we can declare them with integral part up to 999...999
(9
is repeated 308 times). Declaring the integral part with more digits again produces a compile-time error. One thing that interests me is that the compiler seems to allow us specify the fractional part unlimited number of digits. Practically, unlimited number of digits for the fractional part does not make sense.
Questions:
Is there a constant representing the max number of digits internally defined by C# compiler for the fractional part of a floating-point number?
If such a constant exists, why does not C# compiler throw compile-time error when users specify the fractional parts beyond its limit?
namespace FloatingPoint
{
class Program
{
static void Main(string[] args)
{
const ulong @ulong = 18446744073709551615;
const double @double = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
}
}
}
using System;
namespace FloatingPoint
{
class Program
{
static void Main(string[] args)
{
const double x01 = 0.9;
const double x02 = 0.99;
const double x03 = 0.999;
const double x04 = 0.9999;
const double x05 = 0.99999;
const double x06 = 0.999999;
const double x07 = 0.9999999;
const double x08 = 0.99999999;
const double x09 = 0.999999999;
const double x10 = 0.9999999999;
const double x11 = 0.99999999999;
const double x12 = 0.999999999999;
const double x13 = 0.9999999999999;
const double x14 = 0.99999999999999;
const double x15 = 0.999999999999999;
const double x16 = 0.9999999999999999;
const double x17 = 0.99999999999999999;
const double x18 = 0.999999999999999999;
const double x19 = 0.9999999999999999999;
const double x20 = 0.99999999999999999999;
Console.WriteLine(x01);
Console.WriteLine(x02);
Console.WriteLine(x03);
Console.WriteLine(x04);
Console.WriteLine(x05);
Console.WriteLine(x06);
Console.WriteLine(x07);
Console.WriteLine(x08);
Console.WriteLine(x09);
Console.WriteLine(x10);
Console.WriteLine(x11);
Console.WriteLine(x12);
Console.WriteLine(x13);
Console.WriteLine(x14);
Console.WriteLine(x15);
Console.WriteLine(x16);
Console.WriteLine(x17);
Console.WriteLine(x18);
Console.WriteLine(x19);
Console.WriteLine(x20);
}
}
}
/* output:
0.9
0.99
0.999
0.9999
0.99999
0.999999
0.9999999
0.99999999
0.999999999
0.9999999999
0.99999999999
0.999999999999
0.9999999999999
0.99999999999999
0.999999999999999
1
1
1
1
1
*/
IL:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 302 (0x12e)
.maxstack 1
IL_0000: nop
IL_0001: ldc.r8 0.90000000000000002
IL_000a: call void [mscorlib]System.Console::WriteLine(float64)
IL_000f: nop
IL_0010: ldc.r8 0.98999999999999999
IL_0019: call void [mscorlib]System.Console::WriteLine(float64)
IL_001e: nop
IL_001f: ldc.r8 0.999
IL_0028: call void [mscorlib]System.Console::WriteLine(float64)
IL_002d: nop
IL_002e: ldc.r8 0.99990000000000001
IL_0037: call void [mscorlib]System.Console::WriteLine(float64)
IL_003c: nop
IL_003d: ldc.r8 0.99999000000000005
IL_0046: call void [mscorlib]System.Console::WriteLine(float64)
IL_004b: nop
IL_004c: ldc.r8 0.99999899999999997
IL_0055: call void [mscorlib]System.Console::WriteLine(float64)
IL_005a: nop
IL_005b: ldc.r8 0.99999990000000005
IL_0064: call void [mscorlib]System.Console::WriteLine(float64)
IL_0069: nop
IL_006a: ldc.r8 0.99999998999999995
IL_0073: call void [mscorlib]System.Console::WriteLine(float64)
IL_0078: nop
IL_0079: ldc.r8 0.99999999900000003
IL_0082: call void [mscorlib]System.Console::WriteLine(float64)
IL_0087: nop
IL_0088: ldc.r8 0.99999999989999999
IL_0091: call void [mscorlib]System.Console::WriteLine(float64)
IL_0096: nop
IL_0097: ldc.r8 0.99999999999
IL_00a0: call void [mscorlib]System.Console::WriteLine(float64)
IL_00a5: nop
IL_00a6: ldc.r8 0.99999999999900002
IL_00af: call void [mscorlib]System.Console::WriteLine(float64)
IL_00b4: nop
IL_00b5: ldc.r8 0.99999999999989997
IL_00be: call void [mscorlib]System.Console::WriteLine(float64)
IL_00c3: nop
IL_00c4: ldc.r8 0.99999999999999001
IL_00cd: call void [mscorlib]System.Console::WriteLine(float64)
IL_00d2: nop
IL_00d3: ldc.r8 0.999999999999999
IL_00dc: call void [mscorlib]System.Console::WriteLine(float64)
IL_00e1: nop
IL_00e2: ldc.r8 0.99999999999999989
IL_00eb: call void [mscorlib]System.Console::WriteLine(float64)
IL_00f0: nop
IL_00f1: ldc.r8 1.
IL_00fa: call void [mscorlib]System.Console::WriteLine(float64)
IL_00ff: nop
IL_0100: ldc.r8 1.
IL_0109: call void [mscorlib]System.Console::WriteLine(float64)
IL_010e: nop
IL_010f: ldc.r8 1.
IL_0118: call void [mscorlib]System.Console::WriteLine(float64)
IL_011d: nop
IL_011e: ldc.r8 1.
IL_0127: call void [mscorlib]System.Console::WriteLine(float64)
IL_012c: nop
IL_012d: ret
} // end of method Program::Main
0.3
already requires approximation.In most cases, a floating point number will be an approximation of the desired real value anyway (unless it happens to be one of the values that can be represented exactly). Furthermore, the approximation is well-defined: simply round to the nearest representable value. On the other hand, there is no useful way to round an integer (or the integer part of a real number) to the nearest representable value. What does it mean to round 2^100 to 2^64-1, for example?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With