using System.Globalization;
public static void Main()
Console.WriteLine("Exact decimal representation thanks to http://jonskeet.uk/csharp/DoubleConverter.cs\n");
for (int INTPART=1; INTPART >= 0; INTPART--)
for (int ZEROS=0; ZEROS < 5; ZEROS++)
for (int domain=5; domain<10000; domain+=10)
string s = $"{INTPART}.{z}{domain}";
double v = Convert.ToDouble(s);
double ve = Math.Round(v,5,MidpointRounding.ToEven);
double va = Math.Round(v,5,MidpointRounding.AwayFromZero);
string s2 = v.ToString("F5");
double vsv = Convert.ToDouble(s2);
string mark = (va!=vsv) ? "****" : " ";
Console.WriteLine($"{mark} {s}");
Console.WriteLine($"v : {DoubleConverter.ToExactString(v)} {v}");
Console.WriteLine($"va : {DoubleConverter.ToExactString(va)} {va}");
Console.WriteLine($"vsv: {DoubleConverter.ToExactString(vsv)} {vsv}");
Console.WriteLine("done");
public class DoubleConverter
public static string ToExactString (double d)
if (double.IsPositiveInfinity(d))
if (double.IsNegativeInfinity(d))
long bits = BitConverter.DoubleToInt64Bits(d);
bool negative = (bits < 0);
int exponent = (int) ((bits >> 52) & 0x7ffL);
long mantissa = bits & 0xfffffffffffffL;
mantissa = mantissa | (1L<<52);
while((mantissa & 1) == 0)
ArbitraryDecimal ad = new ArbitraryDecimal (mantissa);
for (int i=0; i < -exponent; i++)
for (int i=0; i < exponent; i++)
return "-"+ad.ToString();
internal ArbitraryDecimal (long x)
string tmp = x.ToString(CultureInfo.InvariantCulture);
digits = new byte[tmp.Length];
for (int i=0; i < tmp.Length; i++)
digits[i] = (byte) (tmp[i]-'0');
internal void MultiplyBy(int amount)
byte[] result = new byte[digits.Length+1];
for (int i=digits.Length-1; i >= 0; i--)
int resultDigit = digits[i]*amount+result[i+1];
result[i]=(byte)(resultDigit/10);
result[i+1]=(byte)(resultDigit%10);
Array.Copy (result, 1, digits, 0, digits.Length);
internal void Shift (int amount)
internal void Normalize()
for (first=0; first < digits.Length; first++)
for (last=digits.Length-1; last >= 0; last--)
if (first==0 && last==digits.Length-1)
byte[] tmp = new byte[last-first+1];
for (int i=0; i < tmp.Length; i++)
decimalPoint -= digits.Length-(last+1);
public override String ToString()
char[] digitString = new char[digits.Length];
for (int i=0; i < digits.Length; i++)
digitString[i] = (char)(digits[i]+'0');
return new string (digitString);
return new string (digitString)+
new string ('0', -decimalPoint);
if (decimalPoint >= digitString.Length)
new string ('0',(decimalPoint-digitString.Length))+
new string (digitString);
return new string (digitString, 0,
digitString.Length-decimalPoint)+
digitString.Length-decimalPoint,