Вход Регистрация
Файл: library/Zend/Measure/Number.php
Строк: 401
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category  Zend
 * @package   Zend_Measure
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd     New BSD License
 * @version   $Id: Number.php 20096 2010-01-06 02:05:09Z bkarwin $
 */

/**
 * Implement needed classes
 */
require_once 'Zend/Measure/Abstract.php';
require_once 
'Zend/Locale.php';

/**
 * Class for handling number conversions
 *
 * This class can only handle numbers without precision
 *
 * @category   Zend
 * @package    Zend_Measure
 * @subpackage Zend_Measure_Number
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Measure_Number extends Zend_Measure_Abstract
{
    const 
STANDARD = 'DECIMAL';

    const 
BINARY      = 'BINARY';
    const 
TERNARY     = 'TERNARY';
    const 
QUATERNARY  = 'QUATERNARY';
    const 
QUINARY     = 'QUINARY';
    const 
SENARY      = 'SENARY';
    const 
SEPTENARY   = 'SEPTENARY';
    const 
OCTAL       = 'OCTAL';
    const 
NONARY      = 'NONARY';
    const 
DECIMAL     = 'DECIMAL';
    const 
DUODECIMAL  = 'DUODECIMAL';
    const 
HEXADECIMAL = 'HEXADECIMAL';
    const 
ROMAN       = 'ROMAN';

    
/**
     * Calculations for all number units
     *
     * @var array
     */
    
protected $_units = array(
        
'BINARY'      => array(2,  '⑵'),
        
'TERNARY'     => array(3,  '⑶'),
        
'QUATERNARY'  => array(4,  '⑷'),
        
'QUINARY'     => array(5,  '⑸'),
        
'SENARY'      => array(6,  '⑹'),
        
'SEPTENARY'   => array(7,  '⑺'),
        
'OCTAL'       => array(8,  '⑻'),
        
'NONARY'      => array(9,  '⑼'),
        
'DECIMAL'     => array(10, '⑽'),
        
'DUODECIMAL'  => array(12, '⑿'),
        
'HEXADECIMAL' => array(16, '⒃'),
        
'ROMAN'       => array(99, ''),
        
'STANDARD'    => 'DECIMAL'
    
);

    
/**
     * Definition of all roman signs
     *
     * @var array $_roman
     */
    
private static $_roman = array(
        
'I' => 1,
        
'A' => 4,
        
'V' => 5,
        
'B' => 9,
        
'X' => 10,
        
'E' => 40,
        
'L' => 50,
        
'F' => 90,
        
'C' => 100,
        
'G' => 400,
        
'D' => 500,
        
'H' => 900,
        
'M' => 1000,
        
'J' => 4000,
        
'P' => 5000,
        
'K' => 9000,
        
'Q' => 10000,
        
'N' => 40000,
        
'R' => 50000,
        
'W' => 90000,
        
'S' => 100000,
        
'Y' => 400000,
        
'T' => 500000,
        
'Z' => 900000,
        
'U' => 1000000
    
);

    
/**
     * Convertion table for roman signs
     *
     * @var array $_romanconvert
     */
    
private static $_romanconvert = array(
        
'/_V/' => '/P/',
        
'/_X/' => '/Q/',
        
'/_L/' => '/R/',
        
'/_C/' => '/S/',
        
'/_D/' => '/T/',
        
'/_M/' => '/U/',
        
'/IV/' => '/A/',
        
'/IX/' => '/B/',
        
'/XL/' => '/E/',
        
'/XC/' => '/F/',
        
'/CD/' => '/G/',
        
'/CM/' => '/H/',
        
'/M_V/'=> '/J/',
        
'/MQ/' => '/K/',
        
'/QR/' => '/N/',
        
'/QS/' => '/W/',
        
'/ST/' => '/Y/',
        
'/SU/' => '/Z/'
    
);

    
/**
     * Zend_Measure_Abstract is an abstract class for the different measurement types
     *
     * @param  integer            $value  Value
     * @param  string             $type   (Optional) A Zend_Measure_Number Type
     * @param  string|Zend_Locale $locale (Optional) A Zend_Locale
     * @throws Zend_Measure_Exception When language is unknown
     * @throws Zend_Measure_Exception When type is unknown
     */
    
public function __construct($value, $type, $locale = null)
    {
        if ((
$type !== null) and (Zend_Locale::isLocale($type, null, false))) {
            
$locale = $type;
            
$type = null;
        }

        if (
$locale === null) {
            
$locale = new Zend_Locale();
        }

        if (!
Zend_Locale::isLocale($locale, true, false)) {
            if (!
Zend_Locale::isLocale($locale, true, false)) {
                require_once 
'Zend/Measure/Exception.php';
                throw new 
Zend_Measure_Exception("Language (" . (string) $locale . ") is unknown");
            }

            
$locale = new Zend_Locale($locale);
        }

        
$this->_locale = (string) $locale;

        if (
$type === null) {
            
$type = $this->_units['STANDARD'];
        }

        if (isset(
$this->_units[$type]) === false) {
            require_once 
'Zend/Measure/Exception.php';
            throw new 
Zend_Measure_Exception("Type ($type) is unknown");
        }

        
$this->setValue($value, $type, $this->_locale);
    }

    
/**
     * Set a new value
     *
     * @param  integer            $value  Value
     * @param  string             $type   (Optional) A Zend_Measure_Number Type
     * @param  string|Zend_Locale $locale (Optional) A Zend_Locale Type
     * @throws Zend_Measure_Exception
     */
    
public function setValue($value, $type = null, $locale = null)
    {
        if (empty(
$locale)) {
            
$locale = $this->_locale;
        }

        if (empty(
$this->_units[$type])) {
            require_once 
'Zend/Measure/Exception.php';
            throw new 
Zend_Measure_Exception('unknown type of number:' . $type);
        }

        switch(
$type) {
            case 
'BINARY':
                
preg_match('/[01]+/', $value, $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'TERNARY':
                
preg_match('/[012]+/', $value, $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'QUATERNARY':
                
preg_match('/[0123]+/', $value, $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'QUINARY':
                
preg_match('/[01234]+/', $value, $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'SENARY':
                
preg_match('/[012345]+/', $value, $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'SEPTENARY':
                
preg_match('/[0123456]+/', $value, $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'OCTAL':
                
preg_match('/[01234567]+/', $value, $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'NONARY':
                
preg_match('/[012345678]+/', $value, $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'DUODECIMAL':
                
preg_match('/[0123456789AB]+/', strtoupper($value), $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'HEXADECIMAL':
                
preg_match('/[0123456789ABCDEF]+/', strtoupper($value), $ergebnis);
                
$value = $ergebnis[0];
                break;

            case 
'ROMAN':
                
preg_match('/[IVXLCDM_]+/', strtoupper($value), $ergebnis);
                
$value = $ergebnis[0];
                break;

            default:
                try {
                    
$value = Zend_Locale_Format::getInteger($value, array('locale' => $locale));
                } catch (
Exception $e) {
                    require_once 
'Zend/Measure/Exception.php';
                    throw new 
Zend_Measure_Exception($e->getMessage(), $e->getCode(), $e);
                }
                if (
call_user_func(Zend_Locale_Math::$comp, $value, 0) < 0) {
                    
$value = call_user_func(Zend_Locale_Math::$sqrt, call_user_func(Zend_Locale_Math::$pow, $value, 2));
                }
                break;
        }

        
$this->_value = $value;
        
$this->_type  = $type;
    }

    
/**
     * Convert input to decimal value string
     *
     * @param  integer $input Input string
     * @param  string  $type  Type from which to convert to decimal
     * @return string
     */
    
private function _toDecimal($input, $type)
    {
        
$value = '';
        
// Convert base xx values
        
if ($this->_units[$type][0] <= 16) {
            
$split  = str_split($input);
            
$length = strlen($input);
            for (
$x = 0; $x < $length; ++$x) {
                
$split[$x] = hexdec($split[$x]);
                
$value     = call_user_func(Zend_Locale_Math::$add, $value,
                            
call_user_func(Zend_Locale_Math::$mul, $split[$x],
                            
call_user_func(Zend_Locale_Math::$pow, $this->_units[$type][0], ($length - $x - 1))));
            }
        }

        
// Convert roman numbers
        
if ($type === 'ROMAN') {
            
$input = strtoupper($input);
            
$input = preg_replace(array_keys(self::$_romanconvert), array_values(self::$_romanconvert), $input);

            
$split = preg_split('//', strrev($input), -1, PREG_SPLIT_NO_EMPTY);

            for (
$x =0; $x < sizeof($split); $x++) {
                if (
$split[$x] == '/') {
                    continue;
                }

                
$num = self::$_roman[$split[$x]];
                if ((
$x > 0 and ($split[$x-1] != '/') and ($num < self::$_roman[$split[$x-1]]))) {
                    
$num -= $num;
                }

                
$value += $num;
            }

            
str_replace('/', '', $value);
        }

        return 
$value;
    }

    
/**
     * Convert input to type value string
     *
     * @param  integer $value Input string
     * @param  string  $type  Type to convert to
     * @return string
     * @throws Zend_Measure_Exception When more than 200 digits are calculated
     */
    
private function _fromDecimal($value, $type)
    {
        
$tempvalue = $value;
        if (
$this->_units[$type][0] <= 16) {
            
$newvalue = '';
            
$count    = 200;
            
$base     = $this->_units[$type][0];

            while (
call_user_func(Zend_Locale_Math::$comp, $value, 0, 25) <> 0) {
                
$target = call_user_func(Zend_Locale_Math::$mod, $value, $base);

                
$newvalue = strtoupper(dechex($target)) . $newvalue;

                
$value = call_user_func(Zend_Locale_Math::$sub, $value, $target, 0);
                
$value = call_user_func(Zend_Locale_Math::$div, $value, $base, 0);

                --
$count;
                if (
$count === 0) {
                    require_once 
'Zend/Measure/Exception.php';
                    throw new 
Zend_Measure_Exception("Your value '$tempvalue' cannot be processed because it extends 200 digits");
                }
            }

            if (
$newvalue === '') {
                
$newvalue = '0';
            }
        }

        if (
$type === 'ROMAN') {
            
$i        = 0;
            
$newvalue = '';
            
$romanval = array_values(array_reverse(self::$_roman));
            
$romankey = array_keys(array_reverse(self::$_roman));
            
$count    = 200;
            while (
call_user_func(Zend_Locale_Math::$comp, $value, 0, 25) <> 0) {
                while (
$value >= $romanval[$i]) {
                    
$value    -= $romanval[$i];
                    
$newvalue .= $romankey[$i];

                    if (
$value < 1) {
                        break;
                    }

                    --
$count;
                    if (
$count === 0) {
                        require_once 
'Zend/Measure/Exception.php';
                        throw new 
Zend_Measure_Exception("Your value '$tempvalue' cannot be processed because it extends 200 digits");
                    }
                }

                
$i++;
            }

            
$newvalue = str_replace('/', '', preg_replace(array_values(self::$_romanconvert), array_keys(self::$_romanconvert), $newvalue));
        }

        return 
$newvalue;
    }

    
/**
     * Set a new type, and convert the value
     *
     * @param  string $type New type to set
     * @throws Zend_Measure_Exception When a unknown type is given
     * @return void
     */
    
public function setType($type)
    {
        if (empty(
$this->_units[$type]) === true) {
            require_once 
'Zend/Measure/Exception.php';
            throw new 
Zend_Measure_Exception('Unknown type of number:' . $type);
        }

        
$value = $this->_toDecimal($this->getValue(-1), $this->getType(-1));
        
$value = $this->_fromDecimal($value, $type);

        
$this->_value = $value;
        
$this->_type  = $type;
    }

    
/**
     * Alias function for setType returning the converted unit
     * Default is 0 as this class only handles numbers without precision
     *
     * @param  string  $type  Type to convert to
     * @param  integer $round (Optional) Precision to add, will always be 0
     * @return string
     */
    
public function convertTo($type, $round = 0, $locale = null)
    {
        
$this->setType($type);
        return 
$this->toString($round, $locale);
    }
}
Онлайн: 1
Реклама