SimpleBigDecimal.cs 5.9 KB

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