SimpleBigDecimal.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. using System;
  2. using System.Text;
  3. namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Abc
  4. {
  5. /**
  6. * Class representing a simple version of a big decimal. A
  7. * <code>SimpleBigDecimal</code> is basically a
  8. * {@link java.math.BigInteger BigInteger} with a few digits on the right of
  9. * the decimal point. The number of (binary) digits on the right of the decimal
  10. * point is called the <code>scale</code> of the <code>SimpleBigDecimal</code>.
  11. * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted
  12. * automatically, but must be set manually. All <code>SimpleBigDecimal</code>s
  13. * taking part in the same arithmetic operation must have equal scale. The
  14. * result of a multiplication of two <code>SimpleBigDecimal</code>s returns a
  15. * <code>SimpleBigDecimal</code> with double scale.
  16. */
  17. internal class SimpleBigDecimal
  18. // : Number
  19. {
  20. // private static final long serialVersionUID = 1L;
  21. private readonly BigInteger bigInt;
  22. private readonly int scale;
  23. /**
  24. * Returns a <code>SimpleBigDecimal</code> representing the same numerical
  25. * value as <code>value</code>.
  26. * @param value The value of the <code>SimpleBigDecimal</code> to be
  27. * created.
  28. * @param scale The scale of the <code>SimpleBigDecimal</code> to be
  29. * created.
  30. * @return The such created <code>SimpleBigDecimal</code>.
  31. */
  32. public static SimpleBigDecimal GetInstance(BigInteger val, int scale)
  33. {
  34. return new SimpleBigDecimal(val.ShiftLeft(scale), scale);
  35. }
  36. /**
  37. * Constructor for <code>SimpleBigDecimal</code>. The value of the
  38. * constructed <code>SimpleBigDecimal</code> Equals <code>bigInt /
  39. * 2<sup>scale</sup></code>.
  40. * @param bigInt The <code>bigInt</code> value parameter.
  41. * @param scale The scale of the constructed <code>SimpleBigDecimal</code>.
  42. */
  43. public SimpleBigDecimal(BigInteger bigInt, int scale)
  44. {
  45. if (scale < 0)
  46. throw new ArgumentException("scale may not be negative");
  47. this.bigInt = bigInt;
  48. this.scale = scale;
  49. }
  50. private SimpleBigDecimal(SimpleBigDecimal limBigDec)
  51. {
  52. bigInt = limBigDec.bigInt;
  53. scale = limBigDec.scale;
  54. }
  55. private void CheckScale(SimpleBigDecimal b)
  56. {
  57. if (scale != b.scale)
  58. throw new ArgumentException("Only SimpleBigDecimal of same scale allowed in arithmetic operations");
  59. }
  60. public SimpleBigDecimal AdjustScale(int newScale)
  61. {
  62. if (newScale < 0)
  63. throw new ArgumentException("scale may not be negative");
  64. if (newScale == scale)
  65. return this;
  66. return new SimpleBigDecimal(bigInt.ShiftLeft(newScale - scale), newScale);
  67. }
  68. public SimpleBigDecimal Add(SimpleBigDecimal b)
  69. {
  70. CheckScale(b);
  71. return new SimpleBigDecimal(bigInt.Add(b.bigInt), scale);
  72. }
  73. public SimpleBigDecimal Add(BigInteger b)
  74. {
  75. return new SimpleBigDecimal(bigInt.Add(b.ShiftLeft(scale)), scale);
  76. }
  77. public SimpleBigDecimal Negate()
  78. {
  79. return new SimpleBigDecimal(bigInt.Negate(), scale);
  80. }
  81. public SimpleBigDecimal Subtract(SimpleBigDecimal b)
  82. {
  83. return Add(b.Negate());
  84. }
  85. public SimpleBigDecimal Subtract(BigInteger b)
  86. {
  87. return new SimpleBigDecimal(bigInt.Subtract(b.ShiftLeft(scale)), scale);
  88. }
  89. public SimpleBigDecimal Multiply(SimpleBigDecimal b)
  90. {
  91. CheckScale(b);
  92. return new SimpleBigDecimal(bigInt.Multiply(b.bigInt), scale + scale);
  93. }
  94. public SimpleBigDecimal Multiply(BigInteger b)
  95. {
  96. return new SimpleBigDecimal(bigInt.Multiply(b), scale);
  97. }
  98. public SimpleBigDecimal Divide(SimpleBigDecimal b)
  99. {
  100. CheckScale(b);
  101. BigInteger dividend = bigInt.ShiftLeft(scale);
  102. return new SimpleBigDecimal(dividend.Divide(b.bigInt), scale);
  103. }
  104. public SimpleBigDecimal Divide(BigInteger b)
  105. {
  106. return new SimpleBigDecimal(bigInt.Divide(b), scale);
  107. }
  108. public SimpleBigDecimal ShiftLeft(int n)
  109. {
  110. return new SimpleBigDecimal(bigInt.ShiftLeft(n), scale);
  111. }
  112. public int CompareTo(SimpleBigDecimal val)
  113. {
  114. CheckScale(val);
  115. return bigInt.CompareTo(val.bigInt);
  116. }
  117. public int CompareTo(BigInteger val)
  118. {
  119. return bigInt.CompareTo(val.ShiftLeft(scale));
  120. }
  121. public BigInteger Floor()
  122. {
  123. return bigInt.ShiftRight(scale);
  124. }
  125. public BigInteger Round()
  126. {
  127. SimpleBigDecimal oneHalf = new SimpleBigDecimal(BigInteger.One, 1);
  128. return Add(oneHalf.AdjustScale(scale)).Floor();
  129. }
  130. public int IntValue
  131. {
  132. get { return Floor().IntValue; }
  133. }
  134. public long LongValue
  135. {
  136. get { return Floor().LongValue; }
  137. }
  138. // public double doubleValue()
  139. // {
  140. // return new Double(ToString()).doubleValue();
  141. // }
  142. //
  143. // public float floatValue()
  144. // {
  145. // return new Float(ToString()).floatValue();
  146. // }
  147. public int Scale
  148. {
  149. get { return scale; }
  150. }
  151. public override string ToString()
  152. {
  153. if (scale == 0)
  154. return bigInt.ToString();
  155. BigInteger floorBigInt = Floor();
  156. BigInteger fract = bigInt.Subtract(floorBigInt.ShiftLeft(scale));
  157. if (bigInt.SignValue < 0)
  158. {
  159. fract = BigInteger.One.ShiftLeft(scale).Subtract(fract);
  160. }
  161. if ((floorBigInt.SignValue == -1) && (!(fract.Equals(BigInteger.Zero))))
  162. {
  163. floorBigInt = floorBigInt.Add(BigInteger.One);
  164. }
  165. string leftOfPoint = floorBigInt.ToString();
  166. char[] fractCharArr = new char[scale];
  167. string fractStr = fract.ToString(2);
  168. int fractLen = fractStr.Length;
  169. int zeroes = scale - fractLen;
  170. for (int i = 0; i < zeroes; i++)
  171. {
  172. fractCharArr[i] = '0';
  173. }
  174. for (int j = 0; j < fractLen; j++)
  175. {
  176. fractCharArr[zeroes + j] = fractStr[j];
  177. }
  178. string rightOfPoint = new string(fractCharArr);
  179. StringBuilder sb = new StringBuilder(leftOfPoint);
  180. sb.Append(".");
  181. sb.Append(rightOfPoint);
  182. return sb.ToString();
  183. }
  184. public override bool Equals(
  185. object obj)
  186. {
  187. if (this == obj)
  188. return true;
  189. SimpleBigDecimal other = obj as SimpleBigDecimal;
  190. if (other == null)
  191. return false;
  192. return bigInt.Equals(other.bigInt)
  193. && scale == other.scale;
  194. }
  195. public override int GetHashCode()
  196. {
  197. return bigInt.GetHashCode() ^ scale;
  198. }
  199. }
  200. }