fork download
  1. using System;
  2. using System.Globalization;
  3.  
  4.  
  5. public class Test
  6. {
  7. public static void Main()
  8. {
  9. string inputValue;
  10. while ((inputValue = Console.ReadLine()) != null)
  11. {
  12. double x = double.Parse(inputValue);
  13. string realValue = DoubleConverter.ToExactString(x);
  14. Console.WriteLine($"{inputValue} is actually {realValue}");
  15. }
  16. }
  17. }
  18.  
  19. /// <summary>
  20. /// A class to allow the conversion of doubles to string representations of
  21. /// their exact decimal values. The implementation aims for readability over
  22. /// efficiency.
  23. /// </summary>
  24. public class DoubleConverter
  25. {
  26. /// <summary>
  27. /// Converts the given double to a string representation of its
  28. /// exact decimal value.
  29. /// </summary>
  30. /// <param name="d">The double to convert.</param>
  31. /// <returns>A string representation of the double's exact decimal value.</return>
  32. public static string ToExactString (double d)
  33. {
  34. if (double.IsPositiveInfinity(d))
  35. return "+Infinity";
  36. if (double.IsNegativeInfinity(d))
  37. return "-Infinity";
  38. if (double.IsNaN(d))
  39. return "NaN";
  40.  
  41. // Translate the double into sign, exponent and mantissa.
  42. long bits = BitConverter.DoubleToInt64Bits(d);
  43. // Note that the shift is sign-extended, hence the test against -1 not 1
  44. bool negative = (bits < 0);
  45. int exponent = (int) ((bits >> 52) & 0x7ffL);
  46. long mantissa = bits & 0xfffffffffffffL;
  47.  
  48. // Subnormal numbers; exponent is effectively one higher,
  49. // but there's no extra normalisation bit in the mantissa
  50. if (exponent==0)
  51. {
  52. exponent++;
  53. }
  54. // Normal numbers; leave exponent as it is but add extra
  55. // bit to the front of the mantissa
  56. else
  57. {
  58. mantissa = mantissa | (1L<<52);
  59. }
  60.  
  61. // Bias the exponent. It's actually biased by 1023, but we're
  62. // treating the mantissa as m.0 rather than 0.m, so we need
  63. // to subtract another 52 from it.
  64. exponent -= 1075;
  65.  
  66. if (mantissa == 0)
  67. {
  68. return "0";
  69. }
  70.  
  71. /* Normalize */
  72. while((mantissa & 1) == 0)
  73. { /* i.e., Mantissa is even */
  74. mantissa >>= 1;
  75. exponent++;
  76. }
  77.  
  78. /// Construct a new decimal expansion with the mantissa
  79. ArbitraryDecimal ad = new ArbitraryDecimal (mantissa);
  80.  
  81. // If the exponent is less than 0, we need to repeatedly
  82. // divide by 2 - which is the equivalent of multiplying
  83. // by 5 and dividing by 10.
  84. if (exponent < 0)
  85. {
  86. for (int i=0; i < -exponent; i++)
  87. ad.MultiplyBy(5);
  88. ad.Shift(-exponent);
  89. }
  90. // Otherwise, we need to repeatedly multiply by 2
  91. else
  92. {
  93. for (int i=0; i < exponent; i++)
  94. ad.MultiplyBy(2);
  95. }
  96.  
  97. // Finally, return the string with an appropriate sign
  98. if (negative)
  99. return "-"+ad.ToString();
  100. else
  101. return ad.ToString();
  102. }
  103.  
  104. /// <summary>Private class used for manipulating
  105. class ArbitraryDecimal
  106. {
  107. /// <summary>Digits in the decimal expansion, one byte per digit
  108. byte[] digits;
  109. /// <summary>
  110. /// How many digits are *after* the decimal point
  111. /// </summary>
  112. int decimalPoint=0;
  113.  
  114. /// <summary>
  115. /// Constructs an arbitrary decimal expansion from the given long.
  116. /// The long must not be negative.
  117. /// </summary>
  118. internal ArbitraryDecimal (long x)
  119. {
  120. string tmp = x.ToString(CultureInfo.InvariantCulture);
  121. digits = new byte[tmp.Length];
  122. for (int i=0; i < tmp.Length; i++)
  123. digits[i] = (byte) (tmp[i]-'0');
  124. Normalize();
  125. }
  126.  
  127. /// <summary>
  128. /// Multiplies the current expansion by the given amount, which should
  129. /// only be 2 or 5.
  130. /// </summary>
  131. internal void MultiplyBy(int amount)
  132. {
  133. byte[] result = new byte[digits.Length+1];
  134. for (int i=digits.Length-1; i >= 0; i--)
  135. {
  136. int resultDigit = digits[i]*amount+result[i+1];
  137. result[i]=(byte)(resultDigit/10);
  138. result[i+1]=(byte)(resultDigit%10);
  139. }
  140. if (result[0] != 0)
  141. {
  142. digits=result;
  143. }
  144. else
  145. {
  146. Array.Copy (result, 1, digits, 0, digits.Length);
  147. }
  148. Normalize();
  149. }
  150.  
  151. /// <summary>
  152. /// Shifts the decimal point; a negative value makes
  153. /// the decimal expansion bigger (as fewer digits come after the
  154. /// decimal place) and a positive value makes the decimal
  155. /// expansion smaller.
  156. /// </summary>
  157. internal void Shift (int amount)
  158. {
  159. decimalPoint += amount;
  160. }
  161.  
  162. /// <summary>
  163. /// Removes leading/trailing zeroes from the expansion.
  164. /// </summary>
  165. internal void Normalize()
  166. {
  167. int first;
  168. for (first=0; first < digits.Length; first++)
  169. if (digits[first]!=0)
  170. break;
  171. int last;
  172. for (last=digits.Length-1; last >= 0; last--)
  173. if (digits[last]!=0)
  174. break;
  175.  
  176. if (first==0 && last==digits.Length-1)
  177. return;
  178.  
  179. byte[] tmp = new byte[last-first+1];
  180. for (int i=0; i < tmp.Length; i++)
  181. tmp[i]=digits[i+first];
  182.  
  183. decimalPoint -= digits.Length-(last+1);
  184. digits=tmp;
  185. }
  186.  
  187. /// <summary>
  188. /// Converts the value to a proper decimal string representation.
  189. /// </summary>
  190. public override String ToString()
  191. {
  192. char[] digitString = new char[digits.Length];
  193. for (int i=0; i < digits.Length; i++)
  194. digitString[i] = (char)(digits[i]+'0');
  195.  
  196. // Simplest case - nothing after the decimal point,
  197. // and last real digit is non-zero, eg value=35
  198. if (decimalPoint==0)
  199. {
  200. return new string (digitString);
  201. }
  202.  
  203. // Fairly simple case - nothing after the decimal
  204. // point, but some 0s to add, eg value=350
  205. if (decimalPoint < 0)
  206. {
  207. return new string (digitString)+
  208. new string ('0', -decimalPoint);
  209. }
  210.  
  211. // Nothing before the decimal point, eg 0.035
  212. if (decimalPoint >= digitString.Length)
  213. {
  214. return "0."+
  215. new string ('0',(decimalPoint-digitString.Length))+
  216. new string (digitString);
  217. }
  218.  
  219. // Most complicated case - part of the string comes
  220. // before the decimal point, part comes after it,
  221. // eg 3.5
  222. return new string (digitString, 0,
  223. digitString.Length-decimalPoint)+
  224. "."+
  225. new string (digitString,
  226. digitString.Length-decimalPoint,
  227. decimalPoint);
  228. }
  229. }
  230. }
  231.  
Success #stdin #stdout 0.06s 24032KB
stdin
9.995
0.995
152.995
7.895
stdout
9.995 is actually 9.9949999999999992184029906638897955417633056640625
0.995 is actually 0.99499999999999999555910790149937383830547332763671875
152.995 is actually 152.9950000000000045474735088646411895751953125
7.895 is actually 7.894999999999999573674358543939888477325439453125