Math.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. <?php
  2. /**
  3. * Math.php UTF-8
  4. * 数字处理类
  5. *
  6. * @date : 2018/1/6 16:52
  7. *
  8. * @license 这不是一个自由软件,未经授权不许任何使用和传播。
  9. * @author : guxiannong <gxn@huosdk.com>
  10. * @version : HUOSDK 8.0
  11. */
  12. namespace huolib\tool;
  13. class Math {
  14. const DIV_N = 15;
  15. /**
  16. * 进一法强制保留两位小数
  17. *
  18. * @param $num
  19. *
  20. * @return mixed|string
  21. */
  22. public static function showFloatTwoMax($num) {
  23. return self::accMul(ceil(self::accMul($num, 100)), 0.01);
  24. }
  25. /**
  26. * 两数相加
  27. *
  28. * @param $a
  29. * @param $b
  30. *
  31. * @param int $decimals 保留小数位
  32. *
  33. * @return string
  34. */
  35. public static function addNum($a, $b, $decimals = 2) {
  36. if (!$decimals) {
  37. $decimals = 2;
  38. }
  39. $_n = self::getMaxPoint($a, $b, $decimals);
  40. return number_format((number_format($a, $_n, '.', '') + number_format($b, $_n, '.', '')), $decimals, '.', '');
  41. }
  42. /**
  43. * 两数相加 可正数、负数、小数
  44. *
  45. * @param $a
  46. * @param $b
  47. *
  48. * @return string
  49. */
  50. public static function addBigNum($a, $b) {
  51. $_first_a = substr($a, 0, 1);
  52. $_first_b = substr($b, 0, 1);
  53. if ('-' == $_first_a && '-' == $_first_b) {
  54. return '-'.self::realBigNum(substr($a, 1), substr($b, 1));
  55. } else if ('-' == $_first_a && $_first_b != '-') {
  56. return self::addBigMic($b, substr($a, 1));
  57. } else if ('-' == $_first_b && $_first_a != '-') {
  58. return self::addBigMic($a, substr($b, 1));
  59. } else if ('-' != $_first_b && $_first_a != '-') {
  60. return self::realBigNum($a, $b);
  61. }
  62. }
  63. /**
  64. * 两个大数相加 可带小数
  65. *
  66. * @param $a
  67. * @param $b
  68. *
  69. * @return string
  70. */
  71. public static function realBigNum($a, $b) {
  72. $_la = '';
  73. $_la_l = 0;
  74. if (strpos($a, '.')) {
  75. $_arr_a = explode('.', $a);
  76. if (isset($_arr_a[1])) {
  77. $_la_l = strlen($_arr_a[1]);
  78. $_la = $_arr_a[1];
  79. }
  80. $_la_n = $_arr_a[0];
  81. } else {
  82. $_la_n = $a;
  83. $_la = '';
  84. $_la_l = 0;
  85. }
  86. $_lb = '';
  87. $_lb_l = 0;
  88. if (strpos($b, '.')) {
  89. $_arr_b = explode('.', $b);
  90. if (isset($_arr_b[1])) {
  91. $_lb_l = strlen($_arr_b[1]);
  92. $_lb = $_arr_b[1];
  93. }
  94. $_lb_n = $_arr_b[0];
  95. } else {
  96. $_lb_n = $b;
  97. $_lb = '';
  98. $_lb_l = 0;
  99. }
  100. /* 整数相加 */
  101. $_lr_n = self::realAdd($_la_n, $_lb_n);
  102. /* 小数同位 */
  103. if ($_la_l && $_lb_l) {
  104. if ($_la_l > $_lb_l) {
  105. $_lb = str_pad($_lb, $_la_l, '0', STR_PAD_RIGHT);
  106. } elseif ($_lb_l > $_la_l) {
  107. $_la = str_pad($_la, $_lb_l, '0', STR_PAD_RIGHT);
  108. }
  109. $_lr_low = self::realAdd($_la, $_lb);
  110. $_lr_long = strlen($_lr_low);
  111. $_lr_a = strlen($_la);
  112. if ($_lr_long > $_lr_a) {
  113. $_real_low = substr($_lr_low, $_lr_long - $_lr_a);
  114. $_real_low_n = substr($_lr_low, 0, $_lr_long - $_lr_a);
  115. $_real_n = self::realAdd($_lr_n, $_real_low_n);
  116. return $_real_n.'.'.$_real_low;
  117. }
  118. return $_lr_n.'.'.$_lr_low;
  119. } elseif ($_la_l && !$_lb_l) {
  120. return $_lr_n.'.'.$_la;
  121. } elseif ($_lb_l && !$_la_l) {
  122. return $_lr_n.'.'.$_lb;
  123. } elseif (!$_lb_l && !$_la_l) {
  124. return $_lr_n;
  125. }
  126. }
  127. /**
  128. * 两个大数相减 过滤首尾无用0
  129. *
  130. * @param $a
  131. * @param $b
  132. *
  133. * @return string
  134. */
  135. public static function addBigMic($a, $b) {
  136. $_re = self::realBigMic($a, $b);
  137. if (strpos($_re, '-') === 0) {
  138. $_return_str = ltrim(substr($_re, 1), '0');
  139. if (strpos($_re, '.') === 0) {
  140. return '-0'.rtrim($_return_str);
  141. } else {
  142. return '-'.$_return_str;
  143. }
  144. }
  145. $_return_str = ltrim($_re, '0');
  146. if (strpos($_return_str, '.') === 0) {
  147. return '0'.rtrim($_return_str);
  148. } else {
  149. return $_return_str;
  150. }
  151. }
  152. /**
  153. * 两个大数相减 保留首尾无用0
  154. *
  155. * @param $a
  156. * @param $b
  157. *
  158. * @return string
  159. */
  160. public static function realBigMic($a, $b) {
  161. $_la = '';
  162. $_la_l = 0;
  163. if (strpos($a, '.')) {
  164. $_arr_a = explode('.', $a);
  165. if (isset($_arr_a[1])) {
  166. $_la_l = strlen($_arr_a[1]);
  167. $_la = $_arr_a[1];
  168. }
  169. $_la_n = $_arr_a[0];
  170. } else {
  171. $_la_n = $a;
  172. $_la = '';
  173. $_la_l = 0;
  174. }
  175. $_lb = '';
  176. $_lb_l = 0;
  177. if (strpos($b, '.')) {
  178. $_arr_b = explode('.', $b);
  179. if (isset($_arr_b[1])) {
  180. $_lb_l = strlen($_arr_b[1]);
  181. $_lb = $_arr_b[1];
  182. }
  183. $_lb_n = $_arr_b[0];
  184. } else {
  185. $_lb_n = $b;
  186. $_lb = '';
  187. $_lb_l = 0;
  188. }
  189. /* 整数相减 */
  190. $_lr_n = self::realMic($_la_n, $_lb_n);
  191. /* 小数同位 */
  192. if ($_la_l && $_lb_l) {
  193. if ($_la_l > $_lb_l) {
  194. $_lb = str_pad($_lb, $_la_l, '0', STR_PAD_RIGHT);
  195. } elseif ($_lb_l > $_la_l) {
  196. $_la = str_pad($_la, $_lb_l, '0', STR_PAD_RIGHT);
  197. }
  198. $_lr_low = self::realMic($_la, $_lb);
  199. $_lr_long = strlen($_lr_low);
  200. $_lr_a = strlen($_la);
  201. if ($_lr_long > $_lr_a) {
  202. $_real_low = substr($_lr_low, $_lr_long - $_lr_a);
  203. $_real_n = self::realMic($_lr_n, 1);
  204. return $_real_n.'.'.$_real_low;
  205. }
  206. return $_lr_n.'.'.$_lr_low;
  207. } elseif ($_la_l && !$_lb_l) {
  208. return $_lr_n.'.'.$_la;
  209. } elseif ($_lb_l && !$_la_l) {
  210. return $_lr_n.'.'.$_lb;
  211. } elseif (!$_lb_l && !$_la_l) {
  212. return $_lr_n;
  213. }
  214. }
  215. /**
  216. * 两数相加
  217. *
  218. * @param $a
  219. * @param $b
  220. *
  221. * @return string
  222. */
  223. public static function realAdd($a, $b) {
  224. $a_str = $a.'';
  225. $b_str = $b.'';
  226. $m = strlen($a_str);
  227. $n = strlen($b_str);
  228. $num = $m > $n ? $m : $n;
  229. $result = '';
  230. $flag = 0;
  231. while ($num--) {
  232. $t1 = 0;
  233. $t2 = 0;
  234. if ($m > 0) {
  235. $t1 = $a_str[--$m];
  236. }
  237. if ($n > 0) {
  238. $t2 = $b_str[--$n];
  239. }
  240. $t = $t1 + $t2 + $flag;
  241. if ($t > 9) {
  242. $flag = 1;
  243. $t = $t - 10;
  244. } else {
  245. $flag = 0;
  246. }
  247. $result = $t.$result;
  248. }
  249. if ($flag) {
  250. $result = $flag.$result;
  251. }
  252. return $result;
  253. }
  254. /**
  255. * 两数相减
  256. *
  257. * @param $a
  258. * @param $b
  259. *
  260. * @return string
  261. */
  262. public static function realMic($a, $b) {
  263. $a_str = $a.'';
  264. $b_str = $b.'';
  265. $m = strlen($a_str);
  266. $n = strlen($b_str);
  267. if ($m < $n) {
  268. $_need_flag = true;
  269. $a_str = $b.'';
  270. $_rm = $m;
  271. $m = $n;
  272. $n = $_rm;
  273. unset($_rm);
  274. $b_str = $a.'';
  275. } else {
  276. $_need_flag = false;
  277. }
  278. $num = $m > $n ? $m : $n;
  279. $result = '';
  280. $flag = 0;
  281. while ($num--) {
  282. $t1 = 0;
  283. $t2 = 0;
  284. if ($m > 0) {
  285. $t1 = $a_str[--$m];
  286. }
  287. if ($n > 0) {
  288. $t2 = $b_str[--$n];
  289. }
  290. $_mt = $t2 + $flag;
  291. if ($t1 < $_mt) {
  292. $t = $t1 + 10 - $_mt;
  293. $flag = 1;
  294. } else {
  295. $t = $t1 - $_mt;
  296. $flag = 0;
  297. }
  298. $result = $t.$result;
  299. }
  300. if ($flag) {
  301. $result = '-'.$result;
  302. }
  303. if ($_need_flag) {
  304. $result = '-'.$result;
  305. }
  306. return $result;
  307. }
  308. /**
  309. * 获取指定位数的随机数字
  310. *
  311. * @param int $num 位数
  312. * @param bool $first_zero 是否首位不为零
  313. *
  314. * @return string
  315. */
  316. public static function getRandNum($num = 1, $first_zero = false) {
  317. if (empty($num)) {
  318. return 0;
  319. }
  320. $return_str = '';
  321. for ($i = 0; $i < $num; $i++) {
  322. if ($i == 0 && $first_zero) {
  323. $return_str .= mt_rand(1, 9);
  324. } else {
  325. $return_str .= mt_rand(0, 9);
  326. }
  327. }
  328. return $return_str;
  329. }
  330. /**
  331. * 获取随机手机号码
  332. *
  333. * @return string
  334. */
  335. public static function getRandMobile() {
  336. return '1'.self::getRandNum(10, true);
  337. }
  338. /**
  339. * 获取随机时间
  340. *
  341. * @param int $before 时间上限
  342. * @param int $after 时间下限
  343. *
  344. * @return false|string
  345. */
  346. public static function getRandTime($before = 0, $after = 0) {
  347. if (empty($before) && empty($after)) {
  348. /* 随机0到rand_Max位数的随机数 */
  349. return date('Y-m-d H:i:s', self::getRandNum(mt_rand(0, 20)));
  350. } else {
  351. if ($before - $after > 1) {
  352. return date('Y-m-d H:i:s', $after + intval(mt_rand(0, $before - $after - 1)));
  353. } else {
  354. if ($before > $after) {
  355. return date('Y-m-d H:i:s', mt_rand($after, $before));
  356. } else {
  357. return date('Y-m-d H:i:s');
  358. }
  359. }
  360. }
  361. }
  362. /**
  363. * 获取两数最大的小数点位数
  364. *
  365. * @param $a
  366. * @param $b
  367. * @param int $n 默认位数
  368. *
  369. * @return int
  370. */
  371. public static function getMaxPoint($a, $b, $n = 2) {
  372. $_n = $n;
  373. if (strpos($a, '.') || strpos($b, '.')) {
  374. $_al = self::getNumPoint($a);
  375. if ($_al > $_n) {
  376. $_n = $_al;
  377. }
  378. $_bl = self::getNumPoint($b);
  379. if ($_bl > $_n) {
  380. $_n = $_bl;
  381. }
  382. }
  383. return $_n;
  384. }
  385. /**
  386. * 获取一个数的小数位数
  387. *
  388. * @param $a
  389. *
  390. * @return int
  391. */
  392. public static function getNumPoint($a) {
  393. if (strpos($a, '.')) {
  394. $_arr_a = explode('.', $a);
  395. if (isset($_arr_a[1])) {
  396. return strlen($_arr_a[1]);
  397. }
  398. }
  399. return 0;
  400. }
  401. /**
  402. * 两数相减
  403. *
  404. * @param $a
  405. * @param $b
  406. *
  407. * @param int $decimals 保留位数
  408. *
  409. * @return string
  410. */
  411. public static function addMic($a, $b, $decimals = 2) {
  412. if (!$decimals) {
  413. $decimals = 2;
  414. }
  415. $_n = self::getMaxPoint($a, $b, $decimals);
  416. return number_format((number_format($a, $_n, '.', '') - number_format($b, $_n, '.', '')), $decimals, '.', '');
  417. }
  418. /**
  419. * 两个数精确相乘 小学生算法
  420. *
  421. * @param $strA
  422. * @param $strB
  423. *
  424. * @return mixed|string
  425. */
  426. public static function accMul($strA, $strB) {
  427. $m = 0;
  428. $_al = self::getNumPoint($strA);
  429. $A = $strA;
  430. if ($_al) {
  431. $m = $m + $_al;
  432. $A = str_replace('.', '', $strA);
  433. }
  434. $B = $strB;
  435. $_bl = self::getNumPoint($strB);
  436. if ($_bl) {
  437. $m = $m + $_bl;
  438. $B = str_replace('.', '', $strB);
  439. }
  440. $sResult = "";
  441. //反转字符串
  442. $A = strrev($A);
  443. $B = strrev($B);
  444. $_a_len = strlen($A);
  445. $_b_len = strlen($B);
  446. $_ab_len = $_a_len + $_b_len;
  447. //建立temp变量
  448. $flag = array();
  449. for ($i = 0; $i < ($_ab_len + 1); $i++) {
  450. $flag[$i] = "0";
  451. }
  452. //依次相乘叠加
  453. for ($i = 0; $i < $_a_len; $i++) {
  454. for ($j = 0; $j < $_b_len; $j++) {
  455. $flag[$i + $j] = $flag[$i + $j] + (intval($A[$i]) * intval($B[$j])) % 10;
  456. $flag[$i + $j + 1] = $flag[$i + $j + 1] + (int)((intval($A[$i]) * intval($B[$j])) / 10);
  457. }
  458. }
  459. //再次相乘叠加
  460. for ($i = 0; $i < count($flag) - 1; $i++) {
  461. $flag[$i + 1] = $flag[$i + 1] + (int)(intval($flag[$i]) / 10);
  462. $flag[$i] = intval($flag[$i]) % 10;
  463. }
  464. //去除高位无用的0;
  465. $mark = 0;
  466. for ($i = count($flag) - 1; $i >= 0; $i--) {
  467. if ($flag[$i] != 0 && $mark == 0) {
  468. $mark = $i;
  469. }
  470. if ($mark != 0) {
  471. $sResult = $sResult.$flag[$i];
  472. }
  473. }
  474. if ($sResult == '' && $flag[0] != '') {
  475. $sResult = $flag[0];
  476. }
  477. if ($m) {
  478. $rel = strlen($sResult);
  479. if ($m < $rel) {
  480. return substr($sResult, 0, $rel - $m).'.'.substr($sResult, -$m);
  481. } else {
  482. if ($m == $rel) {
  483. return '0.'.$sResult;
  484. } else {
  485. $re = '0.';
  486. for ($i = 0; $i < $m - $rel; $i++) {
  487. $re .= '0';
  488. }
  489. return $re.$sResult;
  490. }
  491. }
  492. } else {
  493. return $sResult;
  494. }
  495. }
  496. /**
  497. * 高精度除法 php 自带
  498. *
  499. * @param $a
  500. * @param $b
  501. * @param int $n
  502. *$a=bcdiv("111111111111111111","1");
  503. *
  504. * @return string
  505. */
  506. public static function divNum($a, $b, $n = 3) {
  507. return bcdiv($a, $b, $n);
  508. }
  509. /**
  510. * 任意精度除法 a/b 保留n 位小数 用php bcdiv方法
  511. *
  512. * @param $a
  513. * @param $b
  514. * @param $n
  515. *
  516. * @return string
  517. */
  518. public static function phpDivNum($a, $b, $n = 0) {
  519. if (!$n) {
  520. $n = self::DIV_N;
  521. }
  522. $_str_a = $a.'';
  523. $_str_b = $b.'';
  524. /* 先计算符号 */
  525. $_a_one = substr($a, 0, 1);
  526. $_b_one = substr($b, 0, 1);
  527. $_need_flag = false;
  528. if ('-' == $_a_one && '-' == $_b_one) {
  529. $_str_a = substr($a, 1);
  530. $_str_b = substr($b, 1);
  531. $b = $_str_b;
  532. $a = $_str_a;
  533. } elseif ('-' == $_a_one && '-' != $_b_one) {
  534. $_str_a = substr($a, 1);
  535. $a = $_str_a;
  536. $_need_flag = true;
  537. } elseif ('-' != $_a_one && '-' == $_b_one) {
  538. $_str_b = substr($b, 1);
  539. $b = $_str_b;
  540. $_need_flag = true;
  541. } elseif ('-' != $_a_one && '-' != $_b_one) {
  542. }
  543. /* 先计算符号 */
  544. /* 对齐小数点同时去掉小数点 start */
  545. $_an = self::getNumPoint($a);
  546. $_bn = self::getNumPoint($b);
  547. if ($_an > $_bn) {
  548. $_point_str_l = strlen($_str_b) + $_an - $_bn;
  549. $_str_b = str_pad($_str_b, $_point_str_l, '0', STR_PAD_RIGHT);
  550. if ($_an > $n) {
  551. $n = $_an + 1;
  552. }
  553. } elseif ($_bn > $_an) {
  554. $_point_str_l = strlen($_str_a) + $_bn - $_an;
  555. $_str_a = str_pad($_str_a, $_point_str_l, '0', STR_PAD_RIGHT);
  556. if ($_bn > $n) {
  557. $n = $_bn + 1;
  558. }
  559. }
  560. $_str_b = str_replace('.', '', $_str_b);
  561. $_str_a = str_replace('.', '', $_str_a);
  562. /* 对齐小数点同时去掉小数点 end */
  563. $_do_a = str_pad($_str_a, strlen($_str_a) + $n, '0', STR_PAD_RIGHT);
  564. $return_str = self::realDivNum($_do_a, $_str_b, $n);
  565. $_re_z = str_pad('0.', 1 + $n, '0', STR_PAD_RIGHT).'1';
  566. if ($_need_flag) {
  567. return '-'.self::accMul($return_str, $_re_z);
  568. } else {
  569. return self::accMul($return_str, $_re_z);
  570. }
  571. }
  572. /**
  573. * 用php函数计算两数相除精确到 n 个位
  574. *
  575. * @param $a
  576. * @param $b
  577. * @param int $n
  578. *
  579. * @return string
  580. */
  581. public static function realDivNum($a, $b, $n = 0) {
  582. if (!$n) {
  583. $n = self::DIV_N;
  584. }
  585. return self::divNum($a, $b, $n);
  586. }
  587. /**
  588. * 用自己写的小生除法进行计算两个数相除 保留$n 位小数
  589. *
  590. * @param $a
  591. * @param $b
  592. * @param int $n
  593. *
  594. * @return mixed|string
  595. */
  596. public static function bigDivNum($a, $b, $n = 0) {
  597. $_str_a = $a.'';
  598. $_str_b = $b.'';
  599. if (!$n) {
  600. $_n = self::DIV_N;
  601. } else {
  602. $_n = $n + 1;
  603. }
  604. /* 先计算符号 */
  605. $_a_one = substr($a, 0, 1);
  606. $_b_one = substr($b, 0, 1);
  607. $_need_flag = false;
  608. if ('-' == $_a_one && '-' == $_b_one) {
  609. $_str_a = substr($a, 1);
  610. $_str_b = substr($b, 1);
  611. $b = $_str_b;
  612. $a = $_str_a;
  613. } elseif ('-' == $_a_one && '-' != $_b_one) {
  614. $_str_a = substr($a, 1);
  615. $a = $_str_a;
  616. $_need_flag = true;
  617. } elseif ('-' != $_a_one && '-' == $_b_one) {
  618. $_str_b = substr($b, 1);
  619. $b = $_str_b;
  620. $_need_flag = true;
  621. } elseif ('-' != $_a_one && '-' != $_b_one) {
  622. }
  623. /* 先计算符号 */
  624. /* 对齐小数点同时去掉小数点 start */
  625. $_an = self::getNumPoint($a);
  626. $_bn = self::getNumPoint($b);
  627. if ($_an > $_bn) {
  628. $_point_str_l = strlen($_str_b) + $_an - $_bn;
  629. $_str_b = str_pad($_str_b, $_point_str_l, '0', STR_PAD_RIGHT);
  630. if ($_an > $_n) {
  631. $_n = $_an + 1;
  632. }
  633. } elseif ($_bn > $_an) {
  634. $_point_str_l = strlen($_str_a) + $_bn - $_an;
  635. $_str_a = str_pad($_str_a, $_point_str_l, '0', STR_PAD_RIGHT);
  636. if ($_bn > $_n) {
  637. $_n = $_bn + 1;
  638. }
  639. }
  640. $_str_b = str_replace('.', '', $_str_b);
  641. $_str_a = str_replace('.', '', $_str_a);
  642. /* 对齐小数点同时去掉小数点 end */
  643. $_do_a = str_pad($_str_a, strlen($_str_a) + $_n, '0', STR_PAD_RIGHT);
  644. $return_arr = self::getDevFist($_do_a, $_str_b, $_n);
  645. $_re_z = str_pad('0.', 1 + $_n, '0', STR_PAD_RIGHT).'1';
  646. if ($_need_flag) {
  647. return '-'.self::accMul($return_arr['q'], $_re_z);
  648. } else {
  649. return self::accMul($return_arr['q'], $_re_z);
  650. }
  651. }
  652. /**
  653. * 两数相除
  654. * 获得 商和余数
  655. * remainder 余数 quotient 商
  656. *
  657. * @param $a
  658. * @param $b
  659. *
  660. * @param int $n
  661. *
  662. * @return array
  663. */
  664. public static function getDevFist($a, $b, $n = 0) {
  665. $_n = $n + 1;
  666. $_str_la = strlen($a);
  667. $_str_lb = strlen($b);
  668. if (!($_str_la > $_str_lb)) {/* $a的位数大于 $b的位数 商0 余数为a */
  669. return array(
  670. 'q' => '0',
  671. 'r' => $a,
  672. );
  673. }
  674. $_mir = $_str_la - $_str_lb;
  675. if ($_mir < 2) {
  676. return self::getDevRealFist($a, $b);
  677. } else {
  678. $_str_a = $a;
  679. $_str_b = $b;
  680. $_r = str_pad('1', $_mir, '0', STR_PAD_RIGHT);
  681. $_new_b = self::accMul($_str_b, $_r);
  682. $_r_r_arr = self::getDevRealFist($_str_a, $_new_b); /* 取得第一位商 */
  683. $_result = self::accMul($_r_r_arr['q'], $_r);
  684. $_result_r = $_r_r_arr['r'];
  685. $_rr_lr = strlen($_result_r);
  686. if (!($_rr_lr > 1)) {/* 没有余数 */
  687. return array(
  688. 'q' => $_result,
  689. 'r' => $_result_r,
  690. );
  691. }
  692. $_mir_r = $_rr_lr - $_str_lb;
  693. while ($_mir_r > 1 && ($_n > 0)) {
  694. $_r = str_pad('1', $_mir_r, '0', STR_PAD_RIGHT);
  695. $_new_b = self::accMul($b, $_r);
  696. $_r_r_arr = self::getDevRealFist($_result_r, $_new_b); /* 取得第一位商 */
  697. $_result = self::addBigNum($_result, self::accMul($_r_r_arr['q'], $_r));
  698. $_result_r = $_r_r_arr['r'];
  699. $_rr_lr = strlen($_result_r);
  700. if (!($_rr_lr > 1)) {/* 没有余数 */
  701. return array(
  702. 'q' => $_result,
  703. 'r' => $_result_r,
  704. );
  705. }
  706. $_mir_r = $_rr_lr - $_str_lb;
  707. $_n = $_n - 1;
  708. }
  709. $_return_rr = self::getDevRealFist($_result_r, $b);
  710. $_result = self::addBigNum($_result, $_return_rr['q']);
  711. return array(
  712. 'q' => $_result,
  713. 'r' => $_return_rr['r'],
  714. );
  715. }
  716. }
  717. /**
  718. * 获取位数差不大于两位的两数相除的商和余数
  719. *
  720. * @param $a 被除数
  721. * @param $b 除数
  722. *
  723. * @return array
  724. * array(
  725. * '
  726. * )
  727. */
  728. public static function getDevRealFist($a, $b) {
  729. $_str_la = strlen($a);
  730. $_str_lb = strlen($b);
  731. if ($_str_la < $_str_lb) {/* $a的位数大于 $b的位数 商0 余数为a */
  732. return array(
  733. 'q' => '0',
  734. 'r' => $a,
  735. );
  736. }
  737. $_str_a = $a.'';
  738. $_str_b = $b.'';
  739. $_a_one = substr($_str_a, 0, 1);
  740. $_b_one = substr($_str_b, 0, 1);
  741. if ($_str_la == $_str_lb) {
  742. if ($_a_one < $_b_one) {
  743. return array(
  744. 'q' => '0',
  745. 'r' => $a,
  746. );
  747. } elseif ($_a_one == $_b_one) {
  748. $_q_test = self::addBigMic($_str_a, $_str_b);
  749. if ('-' == substr($_q_test, 0, 1)) {
  750. return array(
  751. 'q' => '0',
  752. 'r' => $a,
  753. );
  754. } else {
  755. return array(
  756. 'q' => '1',
  757. 'r' => $_q_test,
  758. );
  759. }
  760. } elseif ($_a_one > $_b_one) {
  761. $_q_test = floor($_a_one / $_b_one);
  762. if (1 == $_q_test) {
  763. $_q_r = self::addBigMic($_str_a, $_str_b);
  764. return array(
  765. 'q' => '1',
  766. 'r' => $_q_r,
  767. );
  768. } else {
  769. $_q_r = self::addBigMic($_str_a, self::accMul($_str_b, $_q_test));
  770. while ('-' == substr($_q_r, 0, 1)) {
  771. $_q_test = $_q_test - 1;
  772. $_q_r = self::addBigMic($_str_a, self::accMul($_str_b, $_q_test));
  773. }
  774. return array(
  775. 'q' => $_q_test,
  776. 'r' => $_q_r,
  777. );
  778. }
  779. }
  780. } elseif ($_str_la > $_str_lb) {
  781. $_min_r = $_str_la - $_str_lb;
  782. if (1 == $_min_r) {/* 被除数比除数多一位 */
  783. $_a_two = substr($_str_a, 0, 2);
  784. $_q_test = floor($_a_two / $_b_one);
  785. if (1 == $_q_test) {
  786. $_q_r = self::addBigMic($_str_a, $_str_b);
  787. return array(
  788. 'q' => '1',
  789. 'r' => $_q_r,
  790. );
  791. } else {
  792. $_q_r = self::addBigMic($_str_a, self::accMul($_str_b, $_q_test));
  793. while ('-' == substr($_q_r, 0, 1)) {
  794. $_q_test = $_q_test - 1;
  795. $_q_r = self::addBigMic($_str_a, self::accMul($_str_b, $_q_test));
  796. }
  797. return array(
  798. 'q' => $_q_test,
  799. 'r' => $_q_r,
  800. );
  801. }
  802. } else {/* 被除数比除数多两位以上 */
  803. return array(
  804. 'q' => 'error',
  805. 'r' => 'a比b多两位或2位以上',
  806. );
  807. }
  808. }
  809. }
  810. }