BcMath.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <?php
  2. namespace app\common\library;
  3. /**
  4. * BC数学函数工具类
  5. * 用于高精度财务计算
  6. */
  7. class BcMath
  8. {
  9. /**
  10. * 默认小数位数
  11. */
  12. const DEFAULT_SCALE = 2;
  13. /**
  14. * 加法运算
  15. * @param string|float|int $left
  16. * @param string|float|int $right
  17. * @param int $scale
  18. * @return string
  19. */
  20. public static function add($left, $right, $scale = self::DEFAULT_SCALE)
  21. {
  22. return bcadd(strval($left), strval($right), $scale);
  23. }
  24. /**
  25. * 减法运算
  26. * @param string|float|int $left
  27. * @param string|float|int $right
  28. * @param int $scale
  29. * @return string
  30. */
  31. public static function sub($left, $right, $scale = self::DEFAULT_SCALE)
  32. {
  33. return bcsub(strval($left), strval($right), $scale);
  34. }
  35. /**
  36. * 乘法运算
  37. * @param string|float|int $left
  38. * @param string|float|int $right
  39. * @param int $scale
  40. * @return string
  41. */
  42. public static function mul($left, $right, $scale = self::DEFAULT_SCALE)
  43. {
  44. return bcmul(strval($left), strval($right), $scale);
  45. }
  46. /**
  47. * 除法运算
  48. * @param string|float|int $left
  49. * @param string|float|int $right
  50. * @param int $scale
  51. * @return string
  52. */
  53. public static function div($left, $right, $scale = self::DEFAULT_SCALE)
  54. {
  55. if (strval($right) === '0' || strval($right) === '0.00') {
  56. return '0.00';
  57. }
  58. return bcdiv(strval($left), strval($right), $scale);
  59. }
  60. /**
  61. * 比较运算
  62. * @param string|float|int $left
  63. * @param string|float|int $right
  64. * @param int $scale
  65. * @return int 1表示left>right,0表示相等,-1表示left<right
  66. */
  67. public static function comp($left, $right, $scale = self::DEFAULT_SCALE)
  68. {
  69. return bccomp(strval($left), strval($right), $scale);
  70. }
  71. /**
  72. * 格式化金额为标准格式
  73. * @param string|float|int $amount
  74. * @param int $scale
  75. * @return string
  76. */
  77. public static function format($amount, $scale = self::DEFAULT_SCALE)
  78. {
  79. return bcadd(strval($amount), '0', $scale);
  80. }
  81. /**
  82. * 确保金额不为负数
  83. * @param string|float|int $amount
  84. * @param int $scale
  85. * @return string
  86. */
  87. public static function max($amount, $scale = self::DEFAULT_SCALE)
  88. {
  89. $formatted = self::format($amount, $scale);
  90. if (self::comp($formatted, '0', $scale) >= 0) {
  91. return $formatted;
  92. }
  93. // 返回0.00格式
  94. return $scale > 0 ? '0.' . str_repeat('0', $scale) : '0';
  95. }
  96. /**
  97. * 计算百分比
  98. * @param string|float|int $amount
  99. * @param string|float|int $percentage
  100. * @param int $scale
  101. * @return string
  102. */
  103. public static function percentage($amount, $percentage, $scale = self::DEFAULT_SCALE)
  104. {
  105. return self::div(self::mul($amount, $percentage, $scale + 2), '100', $scale);
  106. }
  107. /**
  108. * 检查金额是否大于0
  109. * @param string|float|int $amount
  110. * @return bool
  111. */
  112. public static function isPositive($amount)
  113. {
  114. return self::comp($amount, '0') > 0;
  115. }
  116. /**
  117. * 检查金额是否等于0
  118. * @param string|float|int $amount
  119. * @return bool
  120. */
  121. public static function isZero($amount)
  122. {
  123. return self::comp($amount, '0') === 0;
  124. }
  125. /**
  126. * 获取两个金额中的最大值
  127. * @param string|float|int $left
  128. * @param string|float|int $right
  129. * @param int $scale
  130. * @return string
  131. */
  132. public static function maxValue($left, $right, $scale = self::DEFAULT_SCALE)
  133. {
  134. return self::comp($left, $right, $scale) >= 0 ? self::format($left, $scale) : self::format($right, $scale);
  135. }
  136. /**
  137. * 获取两个金额中的最小值
  138. * @param string|float|int $left
  139. * @param string|float|int $right
  140. * @param int $scale
  141. * @return string
  142. */
  143. public static function minValue($left, $right, $scale = self::DEFAULT_SCALE)
  144. {
  145. return self::comp($left, $right, $scale) <= 0 ? self::format($left, $scale) : self::format($right, $scale);
  146. }
  147. }