Ответов: 67 Просмотров: 4610
|
[quote=stolmachev][quote=EuGen]Урок № 5. Математические функции
обещанный вариант Конвертера систем счисления (к уроку №5):
PHP:
скопировать код в буфер обмена
<?PHP class Converter { protected $cipherSet, $rgCiphers, $inputSet, $outputSet, $fromBase, $toBase, $iErrorCode, $sErrorMessage; function __construct($strSet) // Submit only full cipher set. { $this->cipherSet=$strSet; // Note: default initialization proc [constructor?] $this->iErrorCode=0; // may be such: Init(), Converter() and __construct() ! $this->sErrorMessage=""; echo "<br> __construct( \"$strSet\" )"; } protected function baseArithmeticMult($fromBase) //multiplication with non-decimal base { $currentResultLen=count($this->rgCiphers); if ($currentResultLen==0) {return;} $currentPos=0; $div=0; do {$divided=0; if ($currentResultLen>$currentPos) {$divided=$this->rgCiphers[$currentPos]*$fromBase;} $divided+=$div; $rgMods[$currentPos]=$divided%$this->toBase; $div=(int)($divided/$this->toBase); $currentPos++; } while($currentResultLen>$currentPos||$div!=0); $this->rgCiphers=$rgMods; } protected function baseArithmeticPlus($num) //addition with non-decimal base { $currentPos=0; $divided=$num; do { $divided+=(int)($this->rgCiphers[$currentPos]); $this->rgCiphers[$currentPos]=$divided%$this->toBase; $divided=(int)($divided/$this->toBase); $currentPos++; } while ($divided>0); //??? it was erroneous while ($buf>0); +++++ } public function getErrorCode() //error's getters {return $this->iErrorCode;} public function getErrorMessage() {return $this->sErrorMessage;} public function baseConvert($num, $fromBase=0, $toBase=0) //main function { $num=(string)($num); $totalCiphers=strlen($num); // total Ciphers in $num $this->inputSet=substr($this->cipherSet, 0 , $fromBase); // input Set - набор всех возм.цифр для вх.с.с. $this->outputSet=substr($this->cipherSet, 0 , $toBase); //output Set - набор всех цифр для вых.с.с. $this->toBase=$toBase; $this->rgCiphers=array(); $this->iErrorCode=0; // init was absent, need reset for next use of function +++++ for ($currentPos=0; $currentPos<$totalCiphers; $currentPos++) // цикл по всем цифрам конвертируемого числа { $currentCipher=$num[$currentPos]; // current Cipher from current Pos of converting num $cipherSign=substr_count($this->inputSet, $currentCipher); //cipher Sign - счётчик вхождений // подстроки(цифры) в строку исходной с.с. if($cipherSign==0) // нет вхождений - нет такой цифры в исходном наборе с.с. { $this->iErrorCode=254; $this->sErrorMessage="Cipher '".$currentCipher."' not found in cipher set: ".$this->inputSet. " (iErrorCode=$this->iErrorCode)"; return null; } elseif($cipherSign>1) // если входит больше 1 раза - исходный набор с.с. неверен { $this->iErrorCode=255; $this->sErrorMessage="Cipher '".$currentCipher."' found more than once in cipher set: ".$this->inputSet. " (iErrorCode=$this->iErrorCode)"; return null; } if ($currentPos>0) // if ($currentPos!=0) { $this->baseArithmeticMult($fromBase); } $this->baseArithmeticPlus(strpos($this->inputSet, $currentCipher)); //<-(позиция цифры во вход.наборе) } $convertedNum=''; $totalCiphers=count($this->rgCiphers); for ($currentPos=0; $currentPos<$totalCiphers; $currentPos++) { $convertedNum=$this->outputSet[$this->rgCiphers[$currentPos]].$convertedNum; // converted Num } return $convertedNum; } } function pres($n,$fb=10,$tb=2) // print results { global $bc,$Npp; $Npp++; // no serial must be external echo "<br> $Npp) " ; $res = $bc->baseConvert($n,$fb,$tb); echo " baseConvert($n,$fb,$tb)= ", $res; if ($bc->getErrorCode()<>0) echo " ",$bc->getErrorMessage(); } $charset="UTF-8"; //"Windows-1251"; echo " <html> <head> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=$charset\" /> <title>My page in $charset</title> <link rel=\"stylesheet\" type=\"text/css\" href=\"wt.css\" /> </head> <body> "; echo "<h3> Тест BaseConv: </h3> "; echo "<font color= blue face=Arial size=2> "; $bc = new Converter("1223333444455555666666777777788888888999999999aaaaaaaaabcdefghi"); // test BAD Set ! // $bc-> __construct(); // such call is invalid ! $n="1234567890"; $fb=10; $tb=8;// из 10-ричной - в 8-ричную $Npp=-1; pres($n,$fb,$tb); echo "<br>"; $bc = new Converter("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); //$Npp=0; // номер по порядку /* echo "<br> "; //VAR_DUMP("1А3"); echo "<br> "; pres("1А3",10,10); // "русская А" недопустима pres("1A3",10,10); // "латинская А" допустима, но только в с.с. гораздо выше 10-тиричной pres("ABCD",16,10); // из ошибочно-16-ричной - в 10-ричную echo "</font> <br> "; pres("123",10,10); // нормальная, хоть и бессмысленная "конверсия" (для проверки) pres("ABCD",60,10); // из 60-ричной - в 10-ричную pres(7911519,10,60); // из 10-ричной - обратно в 60-ричную pres(254); // из 10-ричной - в 2-ичную (по умолчанию) pres(254,10,16); // из 10-ричной - в 16-ричную pres("254",10,17); // из 10-ричной - в 17-ричную pres("254",10,2); // из 10-ричной - в 2-ичную pres("254",8,2); // из 8-ричной - в 2-ичную pres("10111011",2,16); // из 2-ичной - в 16-ричную pres("10111011",2,8); // из 2-ичной - в 8-ричную pres("273",8,2); // из 8-ричной - обратно в 2-ичную pres("273",8,4); // то же из 8-ичной - в 4-ричную pres("10111011",2,4); // то же из 2-ичной - в 4-ричную pres("10111011",2,3); // то же из 2-ричной - в 3-ичную pres("abcd",16,10); // из 16-ричной - в 10-ричную pres("123",10,8); // из 10-ричной - в 8-ричную pres("1234567890",10,16); // из 10-ричной - в 16-ричную pres("12345.67890",10,16); // из 10-ричной - в 16-ричную - то же, но с дробью pres("1234567890",10,8); // из 10-ричной - в 8-ричную */ pres(254,10,16); // из 10-ричной - в 16-ричную echo "</body> </html> "; ?>
(Добавление)
[quote=stolmachev][quote=stolmachev][quote=EuGen]Урок № 5. Математические функции
Ну, и чтобы поставить точку на этом Конвертере, предложу ещё свой вариант, который мне кажется короче и проще, особенно для начинающих:
PHP:
скопировать код в буфер обмена
<?PHP // Base_Conv2 = // расширение стандартного конвертора систем счисления (base_convert) до A-:-Z (до 61-ричной с.с.) // по умолчанию предполагается преобразование из 10-ной в двоичную с.с. // преобразует в 2 этапа: 1) из входной в 10-ную: $snum = сумма пар сомножителей (вес цифры * вес её разряда); // 2) из 10-ной - в выходную с.с.: цифры результата - это остатки от деления полученной суммы на основание // выходной с.с., взятые в обратном порядке (в цикле каждое следующее делимое - это целая часть частного от // деления, цикл выполяется до тех пор, пока частное не станет == 0). // заметка для себя: знак ^ - это НЕ СТЕПЕНЬ, а XOR!! function base_conv2($num=0, $frombase=10, $tobase=2) { $bastr="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; if ($num==null | $frombase==null | $tobase==null) return NULL; settype($num,"string"); // или $num=(string)($num); $num=implode ("", explode(".", $num)); // вычленение "дробных" ТОЧЕК - всё к целому! //echo "<br> base_conv2: Конверт. с.с.: число $num: ( $frombase -> $tobase ). <br>"; for ($i=--$lnum; $i >= 0; $i--) { $ci=$num[$i]; if ($posi===FALSE) {echo "Цифра $ci недопустима!<br>"; return "Err!";}; if ($posi>=$frombase) {echo "Цифра $ci вне диапазона $frombase-ичной с.с.!<br>"; return "Err!";}; $pow=$lnum-$i; $plus=$posi*pow($frombase,$pow); $nums=$nums + $plus; } $num=$nums; settype($nums,"string"); // === конец 1-го этапа === // if ($tobase==10) return $nums; // === 2-й этап. Если вых.с.с.=10-ичная, то результат уже готов === // $nums=""; do {$ci=$num%$tobase; $num=floor($num/$tobase); $sci=$bastr[$ci]; $nums=$sci.$nums; } while ($num>0); // return $nums; }; // EOFunction base_conv2 ............................................................ echo "<h3> Tест Base_Conv2: </h3> "; // далее - пару десятков проверок echo "<font color= blue> "; // выделение синим примеров с ошибками в аргументах function pres($n,$fb=10,$tb=2) // PRint RESults - проверочная процедура { global $bc,$Npp; $Npp++; // номер п.п. д.быть внешней(глобал.)переменной echo "<br> $Npp) " ; $echores = " my Base_Conv2($n,$fb,$tb)="; $res = base_conv2($n,$fb,$tb); if (!$fb) $fb=10; if (!$tb) $tb=2; // for php Base_Convert: 10 -> 2 (if absent) $echosres = " * * * * * * * php Base_Convert($n,$fb,$tb)="; $sres= base_Convert($n,$fb,$tb); // а что ответит стандартная функция? echo $echores, $res, $echosres, $sres; } //$Npp=0; // номер теста по порядку. в ПХП можно не "инициализировать" нулём :) pres("1А3",10,10); // "русская А" недопустима (но Base_Convert игнорирует нелепые "цифры"!) pres("1A3",10,10); // "латинская А" допустима, но только в с.с. выше 10-ичной pres("ABCD",16,10); // из ошибочно-16- в 10-ичную (НО стандартный конвертер НЕ РАЗЛИЧАЕТ капс!) pres("123",10,10); // нормальная, хоть и бессмысленная "конверсия" (для проверки) pres("ABCD",60,10); // из 60-ричной - в 10-ичную pres(7911519,10,60); // из 10-ичной - обратно в 60-ричную echo "</font> <br> "; pres(254); // из 10-ичной - в 2-ичную (по умолчанию!) pres(254,10,16); // из 10-ичной - в 16-ричную pres("254",10,17); // из 10-ичной - в 17-ричную pres("254",10,2); // из 10-ичной - в 2-ичную pres("254",8,2); // из 8-ричной - в 2-ичную pres("10111011",2,16); // из 2-ичной - в 16-ричную pres("10111011",2,8); // из 2-ичной - в 8-ричную pres("273",8,2); // из 8-ричной - обратно в 2-ичную pres("273",8,4); // то же из 8-ичной - в 4-ричную pres("10111011",2,4); // то же из 2-ичной - в 4-ричную pres("10111011",2,3); // то же из 2-ричной - в 3-ичную pres("abcd",16,10); // из 16-ричной - в 10-ичную pres("123",10,8); // из 10-ичной - в 8-ричную pres("1234567890",10,16); // из 10-ичной - в 16-ричную pres("12345.67890",10,16); // из 10-ичной - в 16-ричную - то же, но с дробью pres("1234567890",10,8); // из 10-ичной - в 8-ричную ?>
|