Source for file Number.class.php

Documentation is available at Number.class.php

  1. <?php
  2. /**
  3. * @since 7/14/05
  4. * @package harmoni.primitives.numbers
  5. *
  6. * @copyright Copyright &copy; 2005, Middlebury College
  7. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)
  8. *
  9. * @version $Id: Number.class.php,v 1.5 2007/09/04 20:25:28 adamfranco Exp $
  10. */
  11. require_once(dirname(__FILE__)."/../Magnitudes/Magnitude.class.php");
  12.  
  13. /**
  14. * This is a partial port of the Squeak/Smalltalk Number class.
  15. *
  16. * Class Number holds the most general methods for dealing with numbers.
  17. * Subclasses Float, Fraction, and Integer, and their subclasses, provide concrete
  18. * representations of a numeric quantity.
  19. *
  20. * All of Number's subclasses participate in a simple type coercion mechanism that
  21. * supports mixed-mode arithmetic and comparisons. It works as follows: If
  22. * self<typeA> op: arg<typeB>
  23. * fails because of incompatible types, then it is retried in the following guise:
  24. * (arg adaptTypeA: self) op: arg adaptToTypeA.
  25. * This gives the arg of typeB an opportunity to resolve the incompatibility, knowing
  26. * exactly what two types are involved. If self is more general, then arg will be
  27. * converted, and viceVersa. This mechanism is extensible to any new number classes
  28. * that one might wish to add to Squeak. The only requirement is that every subclass
  29. * of Number must support a pair of conversion methods specific to each of the other
  30. * subclasses of Number.
  31. *
  32. * To create new Number subclass instances, <b>use one of the static instance-creation
  33. * methods</b>, NOT 'new Integer', etc:
  34. * - {@link withValue Number::withValue($value)}
  35. * - {@link zero Number::zero()}
  36. *
  37. * @since 7/14/05
  38. * @package harmoni.primitives.numbers
  39. *
  40. * @copyright Copyright &copy; 2005, Middlebury College
  41. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)
  42. *
  43. * @version $Id: Number.class.php,v 1.5 2007/09/04 20:25:28 adamfranco Exp $
  44. */
  45. class Number
  46. extends Magnitude
  47. {
  48.  
  49. /*******************************************************
  50. * Class Methods - Instance Creation
  51. *********************************************************/
  52.  
  53.  
  54. /**
  55. * Answer a new object with the value specified
  56. *
  57. * @param mixed $value
  58. * @param optional string $class The class to instantiate. Do NOT use outside
  59. * of this package.
  60. * @return object Number
  61. * @access public
  62. * @since 7/14/05
  63. */
  64. function withValue ( $value, $class = 'Number') {
  65. // Validate our passed class name.
  66. if (!is_subclass_of(new $class, 'Number'))
  67. {
  68. die("Class, '$class', is not a subclass of 'Number'.");
  69. }
  70. $number = new $class;
  71. $number->_setValue($value);
  72. return $number;
  73. }
  74. /**
  75. * Answer a new object with the value specified
  76. *
  77. * @param string $string
  78. * @param optional string $class The class to instantiate. Do NOT use outside
  79. * of this package.
  80. * @return object Number
  81. * @access public
  82. * @since 3/14/06
  83. */
  84. function fromString ( $string, $class = 'Number') {
  85. // Validate our passed class name.
  86. if (!is_subclass_of(new $class, 'Number'))
  87. {
  88. die("Class, '$class', is not a subclass of 'Number'.");
  89. }
  90. $number = new $class;
  91. $number->_setValue($value);
  92. return $number;
  93. }
  94. /**
  95. * Answer a new object with the value zero
  96. *
  97. * @param optional string $class The class to instantiate. Do NOT use outside
  98. * of this package.
  99. * @return object Number
  100. * @access public
  101. * @since 7/14/05
  102. */
  103. function zero ( $class = 'Number') {
  104. eval('$result = '.$class.'::withValue(0);');
  105. return $result;
  106. }
  107. /*******************************************************
  108. * Instance Methods - Arithmatic
  109. *********************************************************/
  110.  
  111. /**
  112. * Answer the sum of the receiver and aNumber.
  113. *
  114. * @param object Number $aNumber
  115. * @return object Number
  116. * @access public
  117. * @since 7/14/05
  118. */
  119. function plus ( $aNumber ) {
  120. die("Method ".__FUNCTION__." in class ".__CLASS__
  121. ." should have been overridden by a child class.");
  122. }
  123. /**
  124. * Answer the difference of the receiver and aNumber.
  125. *
  126. * @param object Number $aNumber
  127. * @return object Number
  128. * @access public
  129. * @since 7/14/05
  130. */
  131. function minus ( $aNumber ) {
  132. return $this->plus($aNumber->negated());
  133. }
  134. /**
  135. * Answer the result of multiplying the receiver and aNumber.
  136. *
  137. * @param object Number $aNumber
  138. * @return object Number
  139. * @access public
  140. * @since 7/14/05
  141. */
  142. function multipliedBy ( $aNumber ) {
  143. die("Method ".__FUNCTION__." in class ".__CLASS__
  144. ." should have been overridden by a child class.");
  145. }
  146. /**
  147. * Answer the result of dividing the receiver and aNumber.
  148. *
  149. * @param object Number $aNumber
  150. * @return object Number
  151. * @access public
  152. * @since 7/14/05
  153. */
  154. function dividedBy ( $aNumber ) {
  155. die("Method ".__FUNCTION__." in class ".__CLASS__
  156. ." should have been overridden by a child class.");
  157. }
  158. /**
  159. * Integer quotient defined by division with truncation toward negative
  160. * infinity. 9//4 = 2, -9//4 = -3. -0.9//0.4 = -3. Modulo (\\) answers the remainder
  161. * from this division.
  162. *
  163. * @param object Number $aNumber
  164. * @return object Number
  165. * @access public
  166. * @since 7/14/05
  167. */
  168. function modIntegerQuotient ( $aNumber ) {
  169. $temp =$this->dividedBy($aNumber);
  170. return $temp->floor();
  171. }
  172. /**
  173. * modulo. Remainder defined in terms of the integerQutient (\\). Answer a
  174. * Number with the same sign as aNumber.
  175. * e.g. 9\\4 = 1, -9\\4 = 3, 9\\-4 = -3, 0.9\\0.4 = 0.1.
  176. *
  177. * @param object Number $aNumber
  178. * @return object Number
  179. * @access public
  180. * @since 7/14/05
  181. */
  182. function modulo ( $aNumber ) {
  183. $temp =$this->integerQuotient($aNumber);
  184. $temp =$temp->multipliedBy($aNumber);
  185. return $this->minus($temp);
  186. }
  187. /**
  188. * Answer a Number that is the absolute value (positive magnitude) of the
  189. * receiver.
  190. *
  191. * @return object Number
  192. * @access public
  193. * @since 7/14/05
  194. */
  195. function abs () {
  196. if ($this->isLessThan(Integer::zero())) {
  197. return $this->negated();
  198. } else {
  199. return $this;
  200. }
  201. }
  202. /**
  203. * Answer a Number that is the negation of the receiver.
  204. *
  205. * @return object Number
  206. * @access public
  207. * @since 7/14/05
  208. */
  209. function negated () {
  210. $zero = Integer::zero();
  211. return $zero->minus($this);
  212. }
  213. /**
  214. * Integer quotient defined by division with truncation toward zero.
  215. * -9 quo: 4 = -2
  216. * -0.9 quo: 0.4 = -2.
  217. * rem: answers the remainder from this division.
  218. *
  219. * @param object Number $aNumber
  220. * @return object Number
  221. * @access public
  222. * @since 7/14/05
  223. */
  224. function remIntegerQuotient ( $aNumber ) {
  225. $temp =$this->dividedBy($aNumber);
  226. return $temp->truncated();
  227. }
  228. /**
  229. * Remainder defined in terms of quo:. Answer a Number with the same
  230. * sign as self. e.g. 9 rem: 4 = 1, -9 rem: 4 = -1. 0.9 rem: 0.4 = 0.1.
  231. *
  232. * @param object Number $aNumber
  233. * @return object Number
  234. * @access public
  235. * @since 7/14/05
  236. */
  237. function remainder ( $aNumber ) {
  238. $temp =$this->remIntegerQuotient($aNumber);
  239. return $this->minus($temp->multipliedBy($aNumber));
  240. }
  241. /**
  242. * Answer 1 divided by the receiver. Create an error notification if the
  243. * receiver is 0.
  244. *
  245. * @param object Number $aNumber
  246. * @return object Number
  247. * @access public
  248. * @since 7/14/05
  249. */
  250. function reciprical () {
  251. if ($this->isEqualTo(Integer::withValue(0)))
  252. throwError(new Error("Division by zero"));
  253. else {
  254. $one = Integer::withValue(1);
  255. return $one->dividedBy($this);
  256. }
  257. }
  258. /*******************************************************
  259. * Instance Methods - Truncation and Rounding
  260. *********************************************************/
  261.  
  262. /**
  263. * Answer the integer nearest the receiver toward positive infinity.
  264. *
  265. * @return object Number
  266. * @access public
  267. * @since 7/14/05
  268. */
  269. function ceiling () {
  270. if ($this->isLessThanOrEqualTo(Integer::zero()))
  271. return $this->truncated();
  272. else {
  273. $temp =$this->negated();
  274. $temp =$temp->floor();
  275. return $temp->negated();
  276. }
  277. }
  278. /**
  279. * Answer the integer nearest the receiver toward negative infinity.
  280. *
  281. * @return object Number
  282. * @access public
  283. * @since 7/14/05
  284. */
  285. function floor () {
  286. $truncation =$this->truncated();
  287. if ($this->isGreaterThanOrEqualTo(Integer::zero()))
  288. return $truncation;
  289. else {
  290. if ($this->isEqualTo($truncation))
  291. return $truncation;
  292. else
  293. return $truncation->minus(Integer::withValue(1));
  294. }
  295. }
  296. /**
  297. * Answer an integer nearest the receiver toward zero.
  298. *
  299. * @return object Number
  300. * @access public
  301. * @since 7/14/05
  302. */
  303. function truncated () {
  304. return $this->remIntegerQuotient(Integer::withValue(1));
  305. }
  306. /*******************************************************
  307. * Instance Methods - Converting
  308. *********************************************************/
  309.  
  310. /**
  311. * Answer a double-precision floating-point number approximating the receiver.
  312. *
  313. * @return Double
  314. * @access public
  315. * @since 7/14/05
  316. */
  317. function asDouble () {
  318. $obj = Double::withValue(doubleval($this->value()));
  319. return $obj;
  320. }
  321. /**
  322. * Answer a floating-point number approximating the receiver.
  323. *
  324. * @return object Float
  325. * @access public
  326. * @since 7/14/05
  327. */
  328. function asFloat () {
  329. $obj = Float::withValue(floatval($this->value()));
  330. return $obj;
  331. }
  332. /**
  333. * Answer an Integer nearest the receiver toward zero.
  334. *
  335. * @return object Integer
  336. * @access public
  337. * @since 7/14/05
  338. */
  339. function asInteger () {
  340. return $this->truncated();
  341. }
  342. /**
  343. * Answer a number.
  344. *
  345. * @return object Number
  346. * @access public
  347. * @since 7/14/05
  348. */
  349. function asNumber () {
  350. return $this;
  351. }
  352. /*******************************************************
  353. * Instance Methods - Comparing
  354. *********************************************************/
  355.  
  356. /**
  357. * Test if this is less than aMagnitude.
  358. *
  359. * @param object Magnitude $aMagnitude
  360. * @return boolean
  361. * @access public
  362. * @since 5/4/05
  363. */
  364. function isLessThan ( $aMagnitude ) {
  365. if (!method_exists($aMagnitude, 'asFloat'))
  366. return false;
  367. $asFloat =$aMagnitude->asFloat();
  368. return ($this->value() < $asFloat->value())?true:false;
  369. }
  370. /**
  371. * Answer whether the receiver and the argument are the same.
  372. * If = is redefined in any subclass, consider also redefining the
  373. * message hash.
  374. *
  375. * @param object $anObject
  376. * @return boolean
  377. * @access public
  378. * @since 7/11/05
  379. */
  380. function isEqualTo ( $anObject ) {
  381. if (!method_exists($anObject, 'asFloat'))
  382. return false;
  383. $asFloat =$anObject->asFloat();
  384. return ($this->value() == $asFloat->value())?true:false;
  385. }
  386. /*******************************************************
  387. * Instance Methods - Printing/Accessing
  388. *********************************************************/
  389.  
  390. /**
  391. * Answer a String whose characters are a description of the receiver.
  392. * Override this method as needed to provide a better representation
  393. *
  394. * @return string
  395. * @access public
  396. * @since 7/11/05
  397. */
  398. function printableString () {
  399. return (string) $this->value();
  400. }
  401. /**
  402. * Answer the PHP primitive value of the reciever.
  403. *
  404. * @return mixed may be an int, float, double, etcetera
  405. * @access public
  406. * @since 7/14/05
  407. */
  408. function value () {
  409. return $this->_value;
  410. }
  411. /*******************************************************
  412. * Instance Methods - Private
  413. *********************************************************/
  414.  
  415. /**
  416. * Set the internal value to a PHP primitive.
  417. *
  418. * @param mixed $value
  419. * @return void
  420. * @access private
  421. * @since 7/14/05
  422. */
  423. function _setValue ( $value ) {
  424. die("Method ".__FUNCTION__." in class ".__CLASS__
  425. ." should have been overridden by a child class.");
  426. }
  427. }
  428.  
  429. ?>

Documentation generated on Wed, 19 Sep 2007 10:25:17 -0400 by phpDocumentor 1.3.0RC3