Bug fix for provider Insurance Numbers
[openemr.git] / library / classes / NumberToText.class.php
blobbe14a04894c573a605f118f1a4dbb5e90b50aad4
1 <?php
3 //pulled from www.djgeespot.com/php, reworked as a class
5 /** Serialized Array of big names, thousand, million, etc
6 * @package NumberToText */
7 define("N2T_BIG", serialize(array('thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion', 'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion', 'quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion', 'vigintillion')));
8 /** Serialized Array of medium names, twenty, thirty, etc
9 * @package NumberToText */
10 define("N2T_MEDIUM", serialize(array(2=>'twenty', 3=>'thirty', 4=>'forty', 5=>'fifty', 6=>'sixty', 7=>'seventy', 8=>'eighty', 9=>'ninety')));
11 /** Serialized Array of small names, zero, one, etc.. up to eighteen, nineteen
12 * @package NumberToText */
13 define("N2T_SMALL", serialize(array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen')));
14 /** Word for "dollars"
15 * @package NumberToText */
16 define("N2T_DOLLARS", "dollars");
17 /** Word for one "dollar"
18 * @package NumberToText */
19 define("N2T_DOLLARS_ONE", "dollar");
20 /** Word for "cents"
21 * @package NumberToText */
22 define("N2T_CENTS", "cents");
23 /** Word for one "cent"
24 * @package NumberToText */
25 define("N2T_CENTS_ONE", "cent");
26 /** Word for "and"
27 * @package NumberToText */
28 define("N2T_AND", "and");
29 /** Word for "negative"
30 * @package NumberToText */
31 define("N2T_NEGATIVE", "negative");
33 class NumberToText {
36 var $number;
37 var $currency;
38 var $capatalize;
39 var $and;
41 function NumberToText($number, $currency = false, $capatalize = false, $and = false) {
42 $this->number = $number;
43 $this->currency = $currency;
44 $this->capatalize = $capatalize;
45 $this->and = $and;
48 /** Number to text converter. Converts a number into a textual description, such as
49 * "one hundred thousand and twenty-five".
51 * Now supports _any_ size number, and negative numbers. To pass numbers > 2 ^32, you must
52 * pass them as a string, as PHP only has 32-bit integers.
54 * @author Greg MacLelan
55 * @version 1.1
56 * @param int $number The number to convert
57 * @param bool $currency True to convert as a dollar amount
58 * @param bool $capatalize True to capatalize every word (except "and")
59 * @param bool $and True to use "and" (ie. "one hundred AND six")
60 * @return The textual description of the number, as a string.
61 * @package NumberToText
64 function convert() {
65 $number = $this->number;
66 $currency = $this->currency;
67 $capatalize = $this->capatalize;
68 $and = $this->and;
70 $big = unserialize(N2T_BIG);
71 $small = unserialize(N2T_SMALL);
73 // get rid of leading 0's
75 while ($number{0} == 0) {
76 $number = substr($number,1);
80 if ($number === 0) {
81 return "zero";
84 $text = "";
86 //$negative = ($number < 0); // check for negative
87 //$number = abs($number); // make sure we have a +ve number
88 if (substr($number, 0, 1) == "-") {
89 $negative = true;
90 $number = substr($number,1); // abs()
91 } else {
92 $negative = false;
95 // get the integer and decimal parts
96 //$int_o = $int = floor($number); // store into two vars
97 if ($pos = strpos($number,".")) {
98 $int_o = $int = substr($number,0,$pos);
99 $decimal_o = $decimal = substr($number,$pos + 1);
100 } else {
101 $int_o = $int = $number;
102 $decimal_o = $decimal = 0;
104 // $int_o and $decimal_o are for "original value"
105 // conversion for integer part:
107 $section = 0; // $section controls "thousand" "million" etc
108 $text = '';
109 do {
110 // keep breaking down into 3 digits ($convert) and the rest
111 //$convert = $int % 1000;
112 //$int = floor($int / 1000);
114 if ($section > count($big) - 1) {
115 // ran out of names for numbers this big, call recursively
116 $text = NumberToText($int, false, false, $and)." ".$big[$section-1]." ".$text;
117 $int = 0;
118 } else {
119 // we can handle it
121 if (strlen($int)<3) {
122 $convert = $int;
123 $int = 0;
124 } else {
125 $convert = substr($int, -3); // grab the last 3 digits
126 $int = substr($int, 0, -1 * strlen($convert));
129 if ($convert > 0) {
130 // we have something here, put it in
131 if ( $section > 0 ) {
132 $text = $this->n2t_convertthree($convert, $and, ($int > 0))." ".$big[$section-1]." ".$text;
133 } else {
134 $text = $this->n2t_convertthree($convert, $and, ($int > 0));
139 $section++;
140 } while ($int > 0);
142 // conversion for decimal part:
144 if ($currency && floor($number)) {
145 // add " dollars"
146 $text .= " ".($int_o == 1 ? N2T_DOLLARS_ONE : N2T_DOLLARS)." ";
149 if ($decimal && $currency) {
150 // if we have any cents, add those
151 if ($int_o > 0) {
152 $text .= " ".N2T_AND." ";
155 $cents = substr($decimal,0,2); // (0.)2342 -> 23
156 $decimal = substr($decimal,2); // (0.)2345.. -> 45..
158 $text .= $this->n2t_convertthree($cents, false, true); // explicitly show "and" if there was an $int
161 if ($decimal) {
162 // any remaining decimals (whether or not $currency is set)
163 $text .= " point";
164 for ($i = 0; $i < strlen($decimal); $i++) {
165 // go through one number at a time
166 $text .= " ".$small[$decimal{$i}];
171 if ($decimal_o && $currency) {
172 // add " cents" (if we're doing currency and had decimals)
173 $text .= " ".($decimal_o == 1 ? N2T_CENTS_ONE : N2T_CENTS);
176 // check for negative
177 if ($negative) {
178 $text = N2T_NEGATIVE." ".$text;
181 // capatalize words
182 if ($capatalize) {
183 // easier to capatalize all words then un-capatalize "and"
184 $text = str_replace(ucwords(N2T_AND), N2T_AND, ucwords($text));
187 return trim($text);
190 /** This is a utility function of n2t. It converts a 3-digit number
191 * into a textual description. Normally this is not called by itself.
193 * @param int $number The 3-digit number to convert (0 - 999)
194 * @param bool $and True to put the "and" in the string
195 * @param bool $preceding True if there are preceding members, puts an
196 * explicit and in (ie 1001 => one thousand AND one)
197 * @return The textual description of the number, as a string
198 * @package NumberToText
200 function n2t_convertthree($number, $and, $preceding) {
201 $small = unserialize(N2T_SMALL);
202 $medium = unserialize(N2T_MEDIUM);
204 $text = "";
206 if ($hundreds = floor($number / 100)) {
207 // we have 100's place
208 $text .= $small[$hundreds]." hundred ";
210 $tens = $number % 100;
211 if ($tens) {
212 // we still have values
213 if ($and && ($hundreds || $preceding)) {
214 $text .= " ".N2T_AND." ";
217 if ($tens < 20) {
218 $text .= $small[$tens];
219 } else {
220 $text .= $medium[floor($tens/10)];
221 if ($ones = $tens % 10) {
222 $text .= "-".$small[$ones];
227 return $text;
230 function getmicrotime(){
231 list($usec, $sec) = explode(" ",microtime());
232 return ((float)$usec + (float)$sec);