// Two basic approaches to numeric validation: // * Built-in functions like 'is_numeric', 'is_int', 'is_float' etc // * Regexes, as shown below $s = '12.345'; preg_match('/\D/', $s) && die("has nondigits\n"); preg_match('/^\d+$/', $s) || die("not a natural number\n"); preg_match('/^-?\d+$/', $s) || die("not an integer\n"); preg_match('/^[+-]?\d+$/', $s) || die("not an integer\n"); preg_match('/^-?\d+\.?\d*$/', $s) || die("not a decimal\n"); preg_match('/^-?(?:\d+(?:\.\d*)?|\.\d+)$/', $s) || die("not a decimal\n"); preg_match('/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/', $s) || die("not a C float\n"); // ---------------------------- function getnum($s) { sscanf($s, "%D", $number); return isset($number) ? $number : 0; } echo getnum(123) . "\n"; // ok echo getnum(0xff) . "\n"; // .. echo getnum(044) . "\n"; // .. echo getnum('x') . "\n"; // fail |
// In PHP floating point comparisions are 'safe' [meaning the '==' comparison operator // can be used] as long as the value consists of 14 digits or less [total digits, either // side of the decimal point e.g. xxxxxxx.xxxxxxx, xxxxxxxxxxxxxx., .xxxxxxxxxxxxxx]. If // values with more digits must be compared, then: // // * Represent as strings, and take care to avoid any implicit conversions e.g. don't pass // a float as a float to a function and expect all digits to be retained - they won't be - // then use 'strcmp' to compare the strings // // * Avoid float use; perhaps use arbitrary precision arithmetic. In this case, the // 'bccomp' function is relevant // Will work as long as each floating point value is 14 digits or less if ($float_1 == $float_2) { ; // ... } // Compare as strings $cmp = strcmp('123456789.123456789123456789', '123456789.123456789123456788'); // Use 'bccomp' $precision = 5; // Number of significant comparison digits after decimal point if (bccomp('1.111117', '1.111116', $precision)) { ; // ... } $precision = 6; if (bccomp('1.111117', '1.111116', $precision)) { ; // ... } // ---------------------------- $wage = 536; $week = $wage * 40; printf("One week's wage is: $%.2f\n", $week / 100); |
// Preferred approach $rounded = round($unrounded, $precision); // Possible alternate approach $format = '%[width].[prec]f'; $rounded = sprintf($format, $unrounded); // ------------ $a = 0.255; $b = round($a, 2); echo "Unrounded: {$a}\nRounded: {$b}\n"; $a = 0.255; $b = sprintf('%.2f', $a); echo "Unrounded: {$a}\nRounded: {$b}\n"; $a = 0.255; printf("Unrounded: %.f\nRounded: %.2f\n", $a, $a); // ---------------------------- echo "number\tint\tfloor\tceil\n"; foreach(array(3.3, 3.5, 3.7, -3.3) as $number) { printf("%.1f\t%.1f\t%.1f\t%.1f\n", $number, (int) $number, floor($number), ceil($number)); } |
// PHP offers the 'bindec' and 'decbin' functions to converting between binary and decimal $num = bindec('0110110'); $binstr = decbin(54); |
foreach (range($X, $Y) as $i) { ; // ... } foreach (range($X, $Y, 7) as $i) { ; // ... } for ($i = $X; $i <= $Y; $i++) { ; // ... } for ($i = $X; $i <= $Y; $i += 7) { ; // ... } // ---------------------------- echo 'Infancy is:'; foreach(range(0, 2) as $i) echo " {$i}\n"; echo 'Toddling is:'; foreach(range(3, 4) as $i) echo " {$i}\n"; echo 'Childhood is:'; foreach(range(5, 12) as $i) echo " {$i}\n"; |
// PHP offers no native support for Roman Numerals. However, a 'Numbers_Roman' class // is available for download from PEAR: [http://pear.php.net/package/Numbers_Roman]. // Note the following 'include' directives are required: // // include_once('Numbers/Roman.php'); $roman = Numbers_Roman::toNumeral($arabic); $arabic = Numbers_Roman::toNumber($roman); // ---------------------------- $roman_fifteen = Numbers_Roman::toNumeral(15); $arabic_fifteen = Numbers_Roman::toNumber($roman_fifteen); printf("Roman for fifteen is: %s\n", $roman_fifteen); printf("Arabic for fifteen is: %d\n", $arabic_fifteen); |
// Techniques used here simply mirror Perl examples, and are not an endorsement // of any particular RNG technique // In PHP do this ... $random = rand($lowerbound, $upperbound); $random = rand($x, $y); // ---------------------------- function make_password($chars, $reqlen) { $len = strlen($chars); for ($i = 0; $i < $reqlen; $i++) $password .= substr($chars, rand(0, $len), 1); return $password; } $chars = 'ABCDEfghijKLMNOpqrstUVWXYz'; $reqlen = 8; $password = make_password($chars, $reqlen); |
// PHP sports a large number of C Standard Library routines including the 'srand' // function, used to re-seed the RNG used with calls to the 'rand' function. Thus, // as per Perl example: while (TRUE) { $seed = (int) fgets(STDIN); if (!empty($seed)) break; } srand($seed); |
// The above is considered - for many reasons - a poor way of seeding the RNG. PHP // also offers alternate versions of the functions, 'mt_srand' and 'mt_rand', // which are described as faster, and more 'random', though key to obtaining a // more 'random' distribution of generated numbers seems to be through using // a combination of a previously saved random value in combination with an // unrepeatable value [like the current time in microseconds] that is multiplied // by a large prime number, or perhaps as part of a hash [examples available in // PHP documentation for 'srand' and 'mt_srand'] mt_srand($saved_random_value + microtime() * 1000003); // or mt_srand(($saved_random_value + hexdec(substr(md5(microtime()), -8))) & 0x7fffffff); // Use of 'mt_rand' together with an appropriate seeding approach should help better // approximate the generation of a 'truly random value' $truly_random_value = mt_rand(); |
function random() { return (float) rand() / (float) getrandmax(); } function gaussian_rand() { $u1 = 0.0; $u2 = 0.0; $g1 = 0.0; $g2 = 0.0; $w = 0.0; do { $u1 = 2.0 * random() - 1.0; $u2 = 2.0 * random() - 1.0; $w = $u1 * $u1 + $u2 * $u2; } while ($w > 1.0); $w = sqrt((-2.0 * log($w)) / $w); $g2 = $u1 * $w; $g1 = $u2 * $w; return $g1; } // ------------ $mean = 25.0; $sdev = 2.0; $salary = gaussian_rand() * $mean + $sdev; printf("You have been hired at: %.2f\n", $salary); |
// 'deg2rad' and 'rad2deg' are actually PHP built-ins, but here is how you might implement / them if needed function deg2rad_($deg) { return ($deg / 180.0) * M_PI; } function rad2deg_($rad) { return ($rad / M_PI) * 180.0; } // ------------ printf("%f\n", deg2rad_(180.0)); printf("%f\n", deg2rad(180.0)); // ---------------------------- function degree_sin($deg) { return sin(deg2rad($deg)); } // ------------ $rad = deg2rad(380.0); printf("%f\n", sin($rad)); printf("%f\n", degree_sin(380.0)); |
function my_tan($theta) { return sin($theta) / cos($theta); } // ------------ $theta = 3.7; printf("%f\n", my_tan($theta)); printf("%f\n", tan($theta)); |
$value = 100.0; $log_e = log($value); $log_10 = log10($value); // ---------------------------- function log_base($base, $value) { return log($value) / log($base); } // ------------ $answer = log_base(10.0, 10000.0); printf("log(10, 10,000) = %f\n", $answer); |
// PHP offers no native support for matrices. However, a 'Math_Matrix' class // is available for download from PEAR: [http://pear.php.net/package/Math_Matrix]. // Note the following 'include' directives are required: // // include_once('Math/Matrix.php'); $a = new Math_Matrix(array(array(3, 2, 3), array(5, 9, 8))); $b = new Math_Matrix(array(array(4, 7), array(9, 3), array(8, 1))); echo $a->toString() . "\n"; echo $b->toString() . "\n"; // NOTE: When I installed this package I had to rename the 'clone' method else // it would not load, so I chose to rename it to 'clone_', and this usage is // shown below. This bug may well be fixed by the time you obtain this package $c = $a->clone_(); $c->multiply($b); echo $c->toString() . "\n"; |
// PHP offers no native support for complex numbers. However, a 'Math_Complex' class // is available for download from PEAR: [http://pear.php.net/package/Math_Complex]. // Note the following 'include' directives are required: // // include_once('Math/Complex.php'); // include_once('Math/TrigOp.php'); // include_once('Math/ComplexOp.php'); $a = new Math_Complex(3, 5); $b = new Math_Complex(2, -2); $c = Math_ComplexOp::mult($a, $b); echo $c->toString() . "\n"; // ---------------------------- $d = new Math_Complex(3, 4); $r = Math_ComplexOp::sqrt($d); echo $r->toString() . "\n"; |
// Like C, PHP supports decimal-alternate notations. Thus, for example, the integer // value, 867, is expressable in literal form as: // // Hexadecimal -> 0x363 // Octal -> 01543 // // For effecting such conversions using strings there is 'sprintf' and 'sscanf'. $dec = 867; $hex = sprintf('%x', $dec); $oct = sprintf('%o', $dec); // ------------ $dec = 0; $hex = '363'; sscanf($hex, '%x', $dec); // ------------ $dec = 0; $oct = '1543'; sscanf($oct, '%o', $dec); // ---------------------------- $number = 0; printf('Gimme a number in decimal, octal, or hex: '); sscanf(fgets(STDIN), '%D', $number); printf("%d %x %o\n", $number, $number, $number); |
// PHP offers the 'number_format' built-in function to, among many other format tasks, // commify numbers. Perl-compatible [as well as extended] regexes are also available function commify_series($s) { return number_format($s, 0, '', ','); } // ------------ $hits = 3456789; printf("Your website received %s accesses last month\n", commify_series($hits)); // ---------------------------- function commify($s) { return strrev(preg_replace('/(\d\d\d)(?=\d)(?!\d*\.)/', '${1},', strrev($s))); } // ------------ $hits = 3456789; echo commify(sprintf("Your website received %d accesses last month\n", $hits)); |
function pluralise($value, $root, $singular='' , $plural='s') { return $root . (($value > 1) ? $plural : $singular); } // ------------ $duration = 1; printf("It took %d %s\n", $duration, pluralise($duration, 'hour')); printf("%d %s %s enough.\n", $duration, pluralise($duration, 'hour'), pluralise($duration, '', 'is', 'are')); $duration = 5; printf("It took %d %s\n", $duration, pluralise($duration, 'hour')); printf("%d %s %s enough.\n", $duration, pluralise($duration, 'hour'), pluralise($duration, '', 'is', 'are')); // ---------------------------- function plural($singular) { $s2p = array('/ss$/' => 'sses', '/([psc]h)$/' => '${1}es', '/z$/' => 'zes', '/ff$/' => 'ffs', '/f$/' => 'ves', '/ey$/' => 'eys', '/y$/' => 'ies', '/ix$/' => 'ices', '/([sx])$/' => '$1es', '$' => 's'); foreach($s2p as $s => $p) { if (preg_match($s, $singular)) return preg_replace($s, $p, $singular); } } // ------------ foreach(array('mess', 'index', 'leaf', 'puppy') as $word) { printf("%6s -> %s\n", $word, plural($word)); } |
// @@INCOMPLETE@@
// @@INCOMPLETE@@
|