Как добавить строки валюты (нестандартизированный ввод) вместе в PHP? - PullRequest
2 голосов
/ 25 сентября 2008

У меня есть форма, в которой люди будут вводить долларовые значения.

Возможные входы:
$ 999,999,999.99
999,999,999.99
999999999
99999
$ 99999

Пользователь может ввести значение в долларах по своему усмотрению. Я хочу прочитать входные данные как двойные, чтобы суммировать их.

Я попытался просто привести тип к двойному, но это не сработало. Всего равно 50 при выводе:

$string1 = "$50,000";
$string2 = "$50000";
$string3 = "50,000";
$total = (double)$string1 + (double)$string2 + (double)$string3;
echo $total;

Ответы [ 7 ]

2 голосов
/ 25 сентября 2008

Вы никогда не хотите представлять денежные значения как числа с плавающей запятой!

Например, возьмите следующий (на первый взгляд, прямой) код:

$x = 1.0;
for ($ii=0; $ii < 10; $ii++) {
  $x = $x - .1;
}
var_dump($x);

Вы можете предположить, что это даст нулевое значение, но это не так. Поскольку $x - это число с плавающей запятой, оно на самом деле оказывается чуть-чуть больше нуля (1.38777878078E-16), что само по себе не имеет большого значения, но это означает, что сравнение значения с другим значением гарантированно будет правильным. Например, $x == 0 выдаст false.

2 голосов
/ 25 сентября 2008

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

Кстати, вы не можете безопасно использовать числа с плавающей точкой при расчете валютных значений. Вы потеряете точность и, возможно, в итоге получите итоговые значения, которые не совсем совпадают с входными данными.

Обновление: вот две функции, которые можно использовать для проверки ввода и преобразования его в представление с десятичной точкой.

function validateCurrency($string)
{
    return preg_match('/^\$?(\d{1,3})(,\d{3})*(.\d{2})?$/', $string) ||
           preg_match('/^\$?\d+(.\d{2})?$/', $string);
}

function makeCurrency($string)
{
    $newstring = "";

    $array = str_split($string);
    foreach($array as $char)
    {
        if (($char >= '0' && $char <= '9') || $char == '.')
        {
            $newstring .= $char;
        }
    }

    return $newstring;
}

Первая функция будет соответствовать большинству форматов валют, которые вы можете ожидать "$ 99", "99,999.00" и т. Д. Она не будет соответствовать ".00" или "99.", а также не будет соответствовать большинству номеров в европейском стиле 99.999,00). Используйте это в исходной строке, чтобы убедиться, что это допустимая строка валюты.

Вторая функция просто удалит все, кроме цифр и десятичных знаков. Обратите внимание, что сам по себе он все еще может возвращать недопустимые строки (например, "", "...." и "abc" выходят как "", "...." и ""). Используйте это, чтобы удалить лишние запятые после проверки строки, или, возможно, используйте это само по себе, если вы хотите пропустить проверку.

0 голосов
/ 25 сентября 2008

Предполагая, что вы получаете реальные денежные значения, вы можете просто удалить символы, которые не являются цифрами или десятичной точкой:

(pseudocode) 
newnumber = replace(oldnumber, /[^0-9.]/, //)

Теперь вы можете конвертировать, используя что-то вроде

double(newnumber)

Однако, это не будет заботиться о таких строках, как "5.6.3" и других подобных неденежных строках. Возникает вопрос: «Вам нужно обрабатывать плохо отформатированные строки?»

0 голосов
/ 25 сентября 2008

Я верю, что вы можете сделать это с помощью printf, которая аналогична функции c с тем же именем. хотя его параметры могут быть несколько эзотерическими. Вы также можете использовать php's number_format function

0 голосов
/ 25 сентября 2008

Я рекомендую не использовать float для хранения валютных значений. Вы можете получить ошибки округления, если сумма становится большой. (Хорошо, если оно становится очень большим.)

Лучше использовать целочисленную переменную с достаточно большим диапазоном и хранить ввод в центах, а не в долларах.

0 голосов
/ 25 сентября 2008

не одна строка, но если вы удалите ', то вы можете сделать: (это псевдокод)

 m/^\$?(\d+)(?:\.(\d\d))?$/
 $value = $1 + $2/100;

Это позволяет $ 9,99, но не $ 9. или $ 9,9 и не может пожаловаться на неправильно расставленные тысячи разделителей (ошибка или особенность?)

Здесь есть потенциальная проблема с местностью, потому что вы предполагаете, что тысячи сделаны с ',' и центами как '.' но в Европе это наоборот (например, 1.000,99)

0 голосов
/ 25 сентября 2008

http://p2p.wrox.com/topic.asp?TOPIC_ID=3099

проходит через это шаг за шагом

[править] типично ... сайт сейчас не работает ...: (

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...