Проверка измерений с помощью PHP

Мне нужно проверить измерения, введенные в форму, созданную PHP.

Я намерен сравнить их с верхними и нижними контрольными пределами и решить, не пройдены они или нет.

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

На данный момент я ожидаю измерения только небольших напряжений и токов, поэтому такие строки, как

'1.234uA', '2.34 nA', '39.9mV'. or '-1.003e-12'

будет преобразован в

1,234e-6, 2,34e-9, 3,99e-2 и -1,003e-12 соответственно.

Но метод должен быть обобщим на любую измеряемую величину.


person pavium    schedule 19.08.2009    source источник


Ответы (3)


function convert($value) {
   $units = array('p' => 'e-12', 
                  'n' => 'e-9', 
                  'u' => 'e-6', 
                  'm' => 'e-3');
   $unitstring = implode("", array_keys($units));
   $matches = array();
   $pattern = "/^(-?(?:\\d*\.\\d+)|(?:\\d+))\s*([$unitstring])([a-z])$/i";
   $result = preg_match($pattern, $value, $matches);
   if ($result) 
      $retval = $matches[1].$units[$matches[2]].$matches[3];
   else
      $retval = $value;
   return $retval;
}

Итак, чтобы объяснить, что делает вышеизложенное:

  • $units — это массив для сопоставления префикса единицы с показателем степени.
  • $unitstring объединяет единицы измерения в одну строку (в примере это будет «pnum»)
  • Регулярное выражение будет соответствовать необязательному -, за которым следует 0 или более цифр, точка и 1 или более цифр ИЛИ 1 или более цифр, за которыми следует один из префиксов единиц измерения (только один), а затем один алфавитный символ. Между числом и единицами измерения может быть любое количество пробелов.
  • Из-за круглых скобок и использования preg_match числовой раздел, префикс единицы измерения и единица измерения по отдельности фиксируются в массиве $matches как элементы 1, 2 и 3. (0 будет содержать всю строку)
  • $result будет равен 1, если он соответствует регулярному выражению, и 0 в противном случае.
  • $retval создается путем простого соединения числа, показателя степени (на основе префикса единиц из массива) и предоставленных единиц, или это будет просто переданная строка (например, если вы получили -1.003e-12). , он будет возвращен)

Кое-что, конечно, можно подправить, но в целом это хорошее начало. Надеюсь, поможет.

person Zeroshade    schedule 20.08.2009
comment
Да, спасибо Зерошейд. Ассоциативный массив, безусловно, проясняет взаимосвязь между префиксом единицы измерения и показателем степени, но это может быть связано с повышенной сложностью следующего кода. Я думаю, что моя фактическая реализация включала дополнительный preg_replace, который удалял пробелы, так что строки, такие как 1,23 uA, стали 1,23e-6. Казалось, это работает хорошо, но мне действительно нравится читабельность вашего ассоциативного массива. - person pavium; 20.08.2009
comment
Спасибо. Единственная большая повышенная сложность здесь — это само регулярное выражение. preg_replace будет дороже, чем просто preg_match. Опять же, если вам нужна скорость и производительность, почему вы используете php? =P Если вы не конвертируете их большое количество за раз (в чем я сомневаюсь, если вы получаете ввод из формы), стоимость сложности, вероятно, будет незначительной. - person Zeroshade; 20.08.2009
comment
Не беспокойтесь о скорости и производительности: я просто проверяю 10 измерений, введенных в форму оператором, который не обязательно знает разницу между пикоампером и микровольтом. Стоимость, о которой я говорил, — это повышенная умственная активность, которую мне пришлось вынести, пока я разбирался в вашем регулярном выражении. Но мне нравится узнавать новое. Спасибо за ваши предложения. - person pavium; 21.08.2009

В вашей функции
сначала вам нужно инициализировать значения для единиц, таких как -6 для u, -3 для m... и т. д.
разделить строку на число и единицу (т.е. микро (u), mili (m), и т.д.).
а затем скажите, что введенное число равно NUM; а единицей измерения является UNIT..(char как u,m и т.д.);

while(NUM>10)
{
NUM=NUM/10;
x++; //x is keeping track of the DOT.
}
UNIT=UNIT+x;    //i.e UNIT is increased(for M,K,etc) or decreased(for u,m,etc)
echo NUM.e.UNIT;

Может и получится!

person RubyDubee    schedule 19.08.2009
comment
Спасибо, Прадьюмна, это просто доказывает, что два человека никогда не решат проблему одинаково. - person pavium; 19.08.2009

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

function convert($value) {
    $result = preg_replace($patterns, $replacements, $value);
    return $result;
}

Где

$patterns = array('/p[av]/i', '/n[av]/i', '/u[av]/i', '/m[av]/i');
$replacements = array('e-12', 'e-9', 'e-6', 'e-3');

И это может быть расширено до более высоких префиксов, но кажется неудобным продолжать добавлять все более сложные регулярные выражения в массив $patterns.

Изменить: сравнение позже должно интерпретировать возвращаемое значение как действительное число.

Я надеюсь, что кто-то может предложить что-то более элегантное.

person pavium    schedule 19.08.2009