2013-11-13 3 views
5

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

Может ли кто-нибудь помочь мне лучше исправить это?

EDIT - Для USD Валюта/нормальные номера

Пример:

1.234 = 1234

-1.234 = -1234

1,234.00 = 1234

1,234.56 = 1234,56

function numberUnformat($number) 
{ 
    $cleanString = preg_replace('/([^0-9\.,])/i', '', $number); 
    $onlyNumbersString = preg_replace('/([^0-9])/i', '', $number); 

    $separatorsCountToBeErased = strlen($cleanString) - strlen($onlyNumbersString) - 1; 

    $stringWithCommaOrDot = preg_replace('/([,\.])/', '', $cleanString, $separatorsCountToBeErased); 
    $removedThousendSeparator = preg_replace('/(\.|,)(?=[0-9]{3,}$)/', '', $stringWithCommaOrDot); 

    return (float) str_replace(',', '.', $removedThousendSeparator); 
} 
+1

ли это необходимость поддержки чисел в многоязычных форматах (т.е. '1.000,01')? –

+0

нет это не хорошо, вопрос – bryan

+0

"unformat" лучше написано "parse" – Eric

ответ

6

Если у вас расширение ICU (которое входит в состав PHP 5.3) доступны, попробуйте следующее:

$formatter = new NumberFormatter('en_US', NumberFormatter::DECIMAL); 
echo $formatter->parse('-1,234.56'); 
+1

Хорошее использование этого расширения. –

+0

Это решение намного яснее, чем использование регулярных выражений. – Jud

0

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

$cleanString = preg_replace('/([^-0-9\.,])/i', '', $number); 
$onlyNumbersString = preg_replace('/([^-0-9])/i', '', $number); 

Хотя это может вызвать проблемы, если у вас есть несколько например 2-434,43.

0

Можно сбросить с регулярными выражениями, чтобы отрицательное, но для меня это проще сделать следующее в конце:

$absvalue = (float) str_replace(',', '.', $removedThousendSeparator); 
if ($number[0] == '-') { 
    $absvalue = $absvalue * -1.0; 
} 
return $absvalue; 

Я мог бы синтаксическую ошибку там, мой PHP ржавый, но идея просто проверить и посмотреть, если входная строка начинается с отрицательным знаком, и если это произойдет, умножьте результат на отрицательной 1.

+1

вы всегда можете использовать ['abs()'] (http://php.net/abs), сохраняет инструкцию if :) – HamZa

2

Измените регулярное выражение, чтобы соответствовать отрицательным числам, тоже:

$cleanString = preg_replace('/([^\-0-9\.,])/i', '', $number); 

Тестовые:

echo numberUnformat('1,234')."\n"; 
echo numberUnformat('-1,234')."\n"; 
echo numberUnformat('1,234.00')."\n"; 
echo numberUnformat('1,234.56 ')."\n"; 

Выход:

1234 
-1234 
1234 
1234.56 

Demo!

+0

Эта работа очень красива, за исключением того, что у меня есть DECIMAL (10,2) в MySQL, которая сохраняя 0,00 в конце. В любом случае, чтобы разобрать это? – bryan

+0

@bryan: Извините, я не понимаю? Не могли бы вы привести пример строки, которая не может заменить это регулярное выражение? –

2

Если вы хотите, чтобы удалить все посторонние знаки минус в середине строки, тоже:

$cleanString = preg_replace('/[^0-9.,-]|(?<=.)-/', '', $number); 
$onlyNumbersString = preg_replace('/[^0-9-]|(?<=.)-/', '', $number); 

Обратите внимание, что вам не нужны скобки, обратная косая черта или /i в оригинале.

+0

Почему вы используете '(? <=.)'? Он просто предотвратит '-', которые находятся в начале строки, которую нужно заменить. – HamZa

+1

@HamZa - точно. Мы хотим сохранить '-' в начале строки и удалить их в другом месте. –

2

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

function number_unformat($num_string, $group_sep = ',', $dec_sep = '.', $cast_to_type = true) { 
    if (substr_count($num_string, $dec_sep) > 1) { 
     // input was invalid 
     throw new Exception('Inavlid string: `' . $num_string . '` passed to function. Too many decimal separators.'); 
    } 
    // remove grouping separator 
    $string = str_replace($group_sep, '', $num_string); 
    if (true === $cast_to_type) { 
     // change any decimal separators to periods before casting 
     $string = str_replace($dec_sep, '.', $string, $count); 
     if ($count === 1) { 
      return (float)$string; 
     } else { 
      return (int)$string; 
     } 
    } else { 
     return $string; 
    } 
} 

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

+0

Это отличный Майк! – bryan

+0

@bryan Спасибо, хотя честно, если вы собираетесь вникать в внутреннее общение вообще, вы можете использовать предложение Андреаса Баумгарта. –

+0

Не очень погружаясь в интернационализацию, просто хотите быть в безопасности в случае опечаток. – bryan

Смежные вопросы