PageRenderTime 98ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Zend/Locale/Math.php

https://github.com/lanmediaservice/lms-tplib
PHP | 312 lines | 154 code | 31 blank | 127 comment | 22 complexity | 61aafccc754c15164684c07c3eeeb82c MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Locale
  17. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Math.php 16221 2009-06-21 19:49:59Z thomas $
  20. */
  21. /**
  22. * Utility class for proxying math function to bcmath functions, if present,
  23. * otherwise to PHP builtin math operators, with limited detection of overflow conditions.
  24. * Sampling of PHP environments and platforms suggests that at least 80% to 90% support bcmath.
  25. * Thus, this file should be as light as possible.
  26. *
  27. * @category Zend
  28. * @package Zend_Locale
  29. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  30. * @license http://framework.zend.com/license/new-bsd New BSD License
  31. */
  32. class Zend_Locale_Math
  33. {
  34. // support unit testing without using bcmath functions
  35. public static $_bcmathDisabled = false;
  36. public static $add = array('Zend_Locale_Math', 'Add');
  37. public static $sub = array('Zend_Locale_Math', 'Sub');
  38. public static $pow = array('Zend_Locale_Math', 'Pow');
  39. public static $mul = array('Zend_Locale_Math', 'Mul');
  40. public static $div = array('Zend_Locale_Math', 'Div');
  41. public static $comp = array('Zend_Locale_Math', 'Comp');
  42. public static $sqrt = array('Zend_Locale_Math', 'Sqrt');
  43. public static $mod = array('Zend_Locale_Math', 'Mod');
  44. public static $scale = 'bcscale';
  45. public static function isBcmathDisabled()
  46. {
  47. return self::$_bcmathDisabled;
  48. }
  49. /**
  50. * Surprisingly, the results of this implementation of round()
  51. * prove better than the native PHP round(). For example, try:
  52. * round(639.795, 2);
  53. * round(267.835, 2);
  54. * round(0.302515, 5);
  55. * round(0.36665, 4);
  56. * then try:
  57. * Zend_Locale_Math::round('639.795', 2);
  58. */
  59. public static function round($op1, $precision = 0)
  60. {
  61. if (self::$_bcmathDisabled) {
  62. return self::normalize(round($op1, $precision));
  63. }
  64. $op1 = trim(self::normalize($op1));
  65. $length = strlen($op1);
  66. if (($decPos = strpos($op1, '.')) === false) {
  67. $op1 .= '.0';
  68. $decPos = $length;
  69. $length += 2;
  70. }
  71. if ($precision < 0 && abs($precision) > $decPos) {
  72. return '0';
  73. }
  74. $digitsBeforeDot = $length - ($decPos + 1);
  75. if ($precision >= ($length - ($decPos + 1))) {
  76. return $op1;
  77. }
  78. if ($precision === 0) {
  79. $triggerPos = 1;
  80. $roundPos = -1;
  81. } elseif ($precision > 0) {
  82. $triggerPos = $precision + 1;
  83. $roundPos = $precision;
  84. } else {
  85. $triggerPos = $precision;
  86. $roundPos = $precision -1;
  87. }
  88. $triggerDigit = $op1[$triggerPos + $decPos];
  89. if ($precision < 0) {
  90. // zero fill digits to the left of the decimal place
  91. $op1 = substr($op1, 0, $decPos + $precision) . str_pad('', abs($precision), '0');
  92. }
  93. if ($triggerDigit >= '5') {
  94. if ($roundPos + $decPos == -1) {
  95. return str_pad('1', $decPos + 1, '0');
  96. }
  97. $roundUp = str_pad('', $length, '0');
  98. $roundUp[$decPos] = '.';
  99. $roundUp[$roundPos + $decPos] = '1';
  100. if ($op1 > 0) {
  101. return self::Add($op1, $roundUp, $precision);
  102. } else {
  103. return self::Sub($op1, $roundUp, $precision);
  104. }
  105. } elseif ($precision >= 0) {
  106. return substr($op1, 0, $decPos + ($precision ? $precision + 1: 0));
  107. }
  108. return (string) $op1;
  109. }
  110. /**
  111. * Normalizes an input to standard english notation
  112. * Fixes a problem of BCMath with setLocale which is PHP related
  113. *
  114. * @param integer $value Value to normalize
  115. * @return string Normalized string without BCMath problems
  116. */
  117. public static function normalize($value)
  118. {
  119. $convert = localeconv();
  120. $value = str_replace($convert['thousands_sep'], "",(string) $value);
  121. $value = str_replace($convert['positive_sign'], "", $value);
  122. $value = str_replace($convert['decimal_point'], ".",$value);
  123. if (!empty($convert['negative_sign']) and (strpos($value, $convert['negative_sign']))) {
  124. $value = str_replace($convert['negative_sign'], "", $value);
  125. $value = "-" . $value;
  126. }
  127. return $value;
  128. }
  129. /**
  130. * Localizes an input from standard english notation
  131. * Fixes a problem of BCMath with setLocale which is PHP related
  132. *
  133. * @param integer $value Value to normalize
  134. * @return string Normalized string without BCMath problems
  135. */
  136. public static function localize($value)
  137. {
  138. $convert = localeconv();
  139. $value = str_replace(".", $convert['decimal_point'], (string) $value);
  140. if (!empty($convert['negative_sign']) and (strpos($value, "-"))) {
  141. $value = str_replace("-", $convert['negative_sign'], $value);
  142. }
  143. return $value;
  144. }
  145. /**
  146. * Changes exponential numbers to plain string numbers
  147. * Fixes a problem of BCMath with numbers containing exponents
  148. *
  149. * @param integer $value Value to erase the exponent
  150. * @param integer $scale (Optional) Scale to use
  151. * @return string
  152. */
  153. public static function exponent($value, $scale = null)
  154. {
  155. if (!extension_loaded('bcmath')) {
  156. return $value;
  157. }
  158. $split = explode('e', $value);
  159. if (count($split) == 1) {
  160. $split = explode('E', $value);
  161. }
  162. if (count($split) > 1) {
  163. $value = bcmul($split[0], bcpow(10, $split[1], $scale), $scale);
  164. }
  165. return $value;
  166. }
  167. /**
  168. * BCAdd - fixes a problem of BCMath and exponential numbers
  169. *
  170. * @param string $op1
  171. * @param string $op2
  172. * @param integer $scale
  173. * @return string
  174. */
  175. public static function Add($op1, $op2, $scale = null)
  176. {
  177. $op1 = self::exponent($op1, $scale);
  178. $op2 = self::exponent($op2, $scale);
  179. return bcadd($op1, $op2, $scale);
  180. }
  181. /**
  182. * BCSub - fixes a problem of BCMath and exponential numbers
  183. *
  184. * @param string $op1
  185. * @param string $op2
  186. * @param integer $scale
  187. * @return string
  188. */
  189. public static function Sub($op1, $op2, $scale = null)
  190. {
  191. $op1 = self::exponent($op1, $scale);
  192. $op2 = self::exponent($op2, $scale);
  193. return bcsub($op1, $op2, $scale);
  194. }
  195. /**
  196. * BCPow - fixes a problem of BCMath and exponential numbers
  197. *
  198. * @param string $op1
  199. * @param string $op2
  200. * @param integer $scale
  201. * @return string
  202. */
  203. public static function Pow($op1, $op2, $scale = null)
  204. {
  205. $op1 = self::exponent($op1, $scale);
  206. $op2 = self::exponent($op2, $scale);
  207. return bcpow($op1, $op2, $scale);
  208. }
  209. /**
  210. * BCMul - fixes a problem of BCMath and exponential numbers
  211. *
  212. * @param string $op1
  213. * @param string $op2
  214. * @param integer $scale
  215. * @return string
  216. */
  217. public static function Mul($op1, $op2, $scale = null)
  218. {
  219. $op1 = self::exponent($op1, $scale);
  220. $op2 = self::exponent($op2, $scale);
  221. return bcmul($op1, $op2, $scale);
  222. }
  223. /**
  224. * BCDiv - fixes a problem of BCMath and exponential numbers
  225. *
  226. * @param string $op1
  227. * @param string $op2
  228. * @param integer $scale
  229. * @return string
  230. */
  231. public static function Div($op1, $op2, $scale = null)
  232. {
  233. $op1 = self::exponent($op1, $scale);
  234. $op2 = self::exponent($op2, $scale);
  235. return bcdiv($op1, $op2, $scale);
  236. }
  237. /**
  238. * BCSqrt - fixes a problem of BCMath and exponential numbers
  239. *
  240. * @param string $op1
  241. * @param integer $scale
  242. * @return string
  243. */
  244. public static function Sqrt($op1, $scale = null)
  245. {
  246. $op1 = self::exponent($op1, $scale);
  247. return bcsqrt($op1, $scale);
  248. }
  249. /**
  250. * BCMod - fixes a problem of BCMath and exponential numbers
  251. *
  252. * @param string $op1
  253. * @param string $op2
  254. * @return string
  255. */
  256. public static function Mod($op1, $op2)
  257. {
  258. $op1 = self::exponent($op1);
  259. $op2 = self::exponent($op2);
  260. return bcmod($op1, $op2);
  261. }
  262. /**
  263. * BCComp - fixes a problem of BCMath and exponential numbers
  264. *
  265. * @param string $op1
  266. * @param string $op2
  267. * @param integer $scale
  268. * @return string
  269. */
  270. public static function Comp($op1, $op2, $scale = null)
  271. {
  272. $op1 = self::exponent($op1, $scale);
  273. $op2 = self::exponent($op2, $scale);
  274. return bccomp($op1, $op2, $scale);
  275. }
  276. }
  277. if ((defined('TESTS_ZEND_LOCALE_BCMATH_ENABLED') && !TESTS_ZEND_LOCALE_BCMATH_ENABLED)
  278. || !extension_loaded('bcmath')) {
  279. //*** require_once 'Zend/Locale/Math/PhpMath.php';
  280. Zend_Locale_Math_PhpMath::disable();
  281. }