Another method, starting with the method:
double i = (10 * 0.69);
Console.Write(ToStringFull(i)); // Output 6.89999999999999946709294817
Console.Write(ToStringFull(-6.9) // Output -6.90000000000000035527136788
Console.Write(ToStringFull(i - 6.9)); // Output -0.00000000000000088817841970012523233890533
public static string ToStringFull(double value)
{
if (value == 0.0) return "0.0";
if (double.IsNaN(value)) return "NaN";
if (double.IsNegativeInfinity(value)) return "-Inf";
if (double.IsPositiveInfinity(value)) return "+Inf";
long bits = BitConverter.DoubleToInt64Bits(value);
BigInteger mantissa = (bits & 0xfffffffffffffL) | 0x10000000000000L;
int exp = (int)((bits >> 52) & 0x7ffL) - 1023;
string sign = (value < 0) ? "-" : "";
if (54 > exp)
{
double offset = (exp / 3.321928094887362358); //...or =Math.Log10(Math.Abs(value))
BigInteger temp = mantissa * BigInteger.Pow(10, 26 - (int)offset) >> (52 - exp);
string numberText = temp.ToString();
int digitsNeeded = (int)((numberText[0] - '5') / 10.0 - offset);
if (exp < 0)
return sign + "0." + new string('0', digitsNeeded) + numberText;
else
return sign + numberText.Insert(1 - digitsNeeded, ".");
}
return sign + (mantissa >> (52 - exp)).ToString();
}
To solve this problem I used the BigInteger tools. Large values are simple as they just require left shifting the mantissa by the exponent. For small values we cannot just directly right shift as that would lose the precision bits. We must first give it some extra size by multiplying it by a 10^n and then do the right shifts. After that, we move over the decimal n places to the left. More text/code here.