G
Guest
The following test program illustrates this point.
Decimal Remainder overflows while calculating near MaxValue.
Decimal Divison fails to get correct answer at MaxValue / 10M or ToString()
is rounding on us quietly ?
Analysis in Debugger leads to
Decimal.MaxValue has sign 0, scale 0, mantissa 0xffff ffff ffff ffff ffff
ffff Decimal.MaxValue/10m has sign 0, scale 0, mantissa 0x1999 9999 9999
9999 9999 999A, which is a rounding of the "correct" mantissa of 0x1999 9999
9999 9999 9999 9999.8 The correct representation of the correct value for
the quotient should have sign 0, scale 1, mantissa 0xffff ffff ffff ffff
ffff ffff
The expression Decimal.MaxValue * 0.1m gives the correct answer.
In particular, the boundary is:
79228162514264337567774146561m/10m gives the wrong answer.
79228162514264337567774146560m/10m comes out even so I can't tell.
79228162514264337567774146559m/10m gives the right answer.
The representation of the wrong answer is sign 0, scale 0, mantissa 0xffff
ffff ffff fffa 0000 0001
The scale of the dividend does not seem to make any difference:
(Decimal.MaxValue*0.1m) / 10m also gives the wrong answer on the division.
No matter what power of 10 the divisor is, you only seem to lose one digit
of precision.
Test Program
using System;
namespace test
{
public class MainTest
{
static public void Main()
{
System.Decimal r1 = Decimal.MaxValue;
System.Decimal r2 = 0.1M;
System.Decimal result;
for( int i = 1; i < 6; ++i)
{
try
{
Console.Write( r1.ToString() + " % " + r2.ToString() + " =" );
result = r1 % r2;
Console.WriteLine( result.ToString());
}
catch( System.Exception e )
{
Console.WriteLine( e.Message );
}
r1 /= 10M;
}
}
}
}
#if OUTPUT
79228162514264337593543950335 % 0.1 =Value was either too large or too small
for a Decimal.
7922816251426433759354395034 % 0.1 =Value was either too large or too small
for a Decimal.
792281625142643375935439503.4 % 0.1 =0
79228162514264337593543950.34 % 0.1 =0.04
7922816251426433759354395.034 % 0.1 =0.034
#endif
Same problem occurs in .NET 2.0 (beta) and has been reported in the beta bug
tracking system.
Decimal Remainder overflows while calculating near MaxValue.
Decimal Divison fails to get correct answer at MaxValue / 10M or ToString()
is rounding on us quietly ?
Analysis in Debugger leads to
Decimal.MaxValue has sign 0, scale 0, mantissa 0xffff ffff ffff ffff ffff
ffff Decimal.MaxValue/10m has sign 0, scale 0, mantissa 0x1999 9999 9999
9999 9999 999A, which is a rounding of the "correct" mantissa of 0x1999 9999
9999 9999 9999 9999.8 The correct representation of the correct value for
the quotient should have sign 0, scale 1, mantissa 0xffff ffff ffff ffff
ffff ffff
The expression Decimal.MaxValue * 0.1m gives the correct answer.
In particular, the boundary is:
79228162514264337567774146561m/10m gives the wrong answer.
79228162514264337567774146560m/10m comes out even so I can't tell.
79228162514264337567774146559m/10m gives the right answer.
The representation of the wrong answer is sign 0, scale 0, mantissa 0xffff
ffff ffff fffa 0000 0001
The scale of the dividend does not seem to make any difference:
(Decimal.MaxValue*0.1m) / 10m also gives the wrong answer on the division.
No matter what power of 10 the divisor is, you only seem to lose one digit
of precision.
Test Program
using System;
namespace test
{
public class MainTest
{
static public void Main()
{
System.Decimal r1 = Decimal.MaxValue;
System.Decimal r2 = 0.1M;
System.Decimal result;
for( int i = 1; i < 6; ++i)
{
try
{
Console.Write( r1.ToString() + " % " + r2.ToString() + " =" );
result = r1 % r2;
Console.WriteLine( result.ToString());
}
catch( System.Exception e )
{
Console.WriteLine( e.Message );
}
r1 /= 10M;
}
}
}
}
#if OUTPUT
79228162514264337593543950335 % 0.1 =Value was either too large or too small
for a Decimal.
7922816251426433759354395034 % 0.1 =Value was either too large or too small
for a Decimal.
792281625142643375935439503.4 % 0.1 =0
79228162514264337593543950.34 % 0.1 =0.04
7922816251426433759354395.034 % 0.1 =0.034
#endif
Same problem occurs in .NET 2.0 (beta) and has been reported in the beta bug
tracking system.