Превращение Float в их ближайшую (UTF-8 персонаж) фракцию - PullRequest
1 голос
/ 15 марта 2010

Я хочу взять любое действительное число и вернуть самое близкое число с самой близкой дробью, доступной в наборе символов UTF-8, соответственно.

0/4 = 0.00 =   # < .125
1/4 = 0.25 = ¼ # > .125 & < .375
2/4 = 0.50 = ½ # > .375 & < .625
3/4 = 0.75 = ¾ # > .625 & < .875
4/4 = 1.00 =   # > .875

Я сделал эту функцию для выполнения этой задачи:

function displayFraction($realNumber)
{
    if (!is_float($realNumber))
    {
        return $realNumber;
    }
    list($number, $decimal) = explode('.', $realNumber);
    $decimal = '.' . $decimal;
    switch($decimal)
    {
        case $decimal < 0.125:
            return $number;
        case $decimal > 0.125 && $decimal < 0.375:
            return $number . '¼'; # 188 ¼ &#188;
        case $decimal > 0.375 && $decimal < 0.625:
            return $number . '½'; # 189 ½ &#189;
        case $decimal > 0.625 && $decimal < 0.875:
            return $number . '¾'; # 190 ¾ &#190;
        case $decimal < 0.875:
            return ++$number;
    }
}

Какой лучший / другой способ сделать это?

echo displayFraction(3.1) . PHP_EOL;      # Outputs: 3
echo displayFraction(3.141593) . PHP_EOL; # Outputs: 3¼
echo displayFraction(3.267432) . PHP_EOL; # Outputs: 3¼
echo displayFraction(3.38) . PHP_EOL;     # Outputs: 3½

Раскрой мой разум!

Ответы [ 3 ]

2 голосов
/ 15 марта 2010

Можно быть «умным» и взять (188 + (десятичное-0,125) * 4) для случая, когда десятичное число находится в диапазоне от 0,125 до 0,875, но это будет более запутанным, чем умное, ИМО. Тем не менее, вы, вероятно, хотите, чтобы ваш последний случай был> 0,875, а не <0,875. </p>

2 голосов
/ 15 марта 2010

Вы реализовали статически скомпилированный алгоритм поиска для выбора фракций. До тех пор, пока количество фракций Юникода не сильно изменится (что не изменится), то то, что у вас есть, хорошо. Двигайся.

Если вы жили в мире, где фракции Юникода часто менялись. Затем вам следует переключить поиск с жесткого кодирования на управляемый данными. Просто есть таблица значений дроби и их Unicode-эквивалент. Найдите в таблице ближайшую дробь, затем используйте связанный символ Юникода.

1 голос
/ 15 марта 2010

Не стоит полагаться на наличие десятичной части:

# Will generate a STRICT warning if $realNumber does not contain a full stop:
list($number, $decimal) = explode('.', $realNumber);

Попробуйте вместо этого:

$integerPart = floor($realNumber);
$decimalPart = $realPart - $integerPart;

Вы не должны использовать переключатель здесь, а вместо операторов if (это будет выглядеть так, как будто это работает, но даст неожиданные результаты, например, если вы введете 0, так как вы фактически сравниваете $decimal с результатом выражения $decimal < 0.125):

if ($decimalPart <= 0.25) {
    # ...
} else if ($decimalPart <= 0.5) {
    # ...
} else if ...
...