Вопрос

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

Коллега частично нашел решение с использованием VB6, но это не совсем так, как показано в приведенной ниже расшифровке.

cliVe> a = 1e6
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 10 exponent: 5 

должно было быть 1 и 6

cliVe> a = 1.1e6
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.1 exponent: 6

правильный

cliVe> a = 123345.6e-7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: -2

правильный

cliVe> a = -123345.6e-7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: -2

должно быть -1.233456 и -2

cliVe> a = -123345.6e+7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: 12

правильный

Есть какие-нибудь идеи?Кстати, Clive - это CLI, основанный на VBScript, и его можно найти на моем блог.

Это было полезно?

Решение

Google на " научное обозначение regexp " показывает число совпадений, включая этот ( не используйте его !!! ! ) который использует

*** warning: questionable ***
/[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/

, который включает в себя такие случаи, как -.5e7 и + 00000e33 (оба из которых вы не можете разрешить).

Вместо этого я бы настоятельно рекомендовал вам использовать синтаксис на сайте JSON Дуга Крокфорда a> который явно документирует, что составляет число в JSON. Вот соответствующая синтаксическая диаграмма, взятая с этой страницы:

 alt text
(источник: json.org )

Если вы посмотрите на строку 456 его json2.js скрипт (безопасное преобразование в / из JSON в javascript), вы увидите эту часть регулярного выражения:

/-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/

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

/-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/

и если вы хотите разрешить начальный +, вы получите:

/[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/

Добавьте захватывающие скобки по своему вкусу.

Я также настоятельно рекомендую вам детализировать несколько тестовых случаев, чтобы убедиться, что вы включаете те возможности, которые вы хотите включить (или не включать), такие как:

allowed:
+3
3.2e23
-4.70e+9
-.2E-4
-7.6603

not allowed:
+0003   (leading zeros)
37.e88  (dot before the e)

Удачи!

Другие советы

Основываясь на ответе с самым высоким рейтингом, я немного изменил регулярное выражение, чтобы оно было /^[+\-]?(?=.)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/.

Преимущества, которые это дает, заключаются в следующем:

  1. позволяет сопоставлять такие числа, как .9 (Я сделал (?:0|[1-9]\d*) опционально с ?)
  2. предотвращает сопоставление только оператора в начале и предотвращает сопоставление строк нулевой длины (использует предварительный просмотр, (?=.))
  3. предотвращает совпадение e9 потому что для этого требуется \d перед научной нотацией

Моя цель в этом - использовать его для получения значимых цифр и выполнения значимых математических расчетов.Поэтому я также собираюсь разделить его на группы захвата следующим образом: /^[+\-]?(?=.)(0|[1-9]\d*)?(\.\d*)?(?:(\d)[eE][+\-]?\d+)?$/.

Объяснение того, как получить значимые цифры из этого:

  1. Весь снимок - это номер, который вы можете передать кому-либо parseFloat()
  2. Совпадения 1-3 будут отображаться как неопределенные или строки, поэтому объедините их (замените undefined"это с '') должен указывать исходное число, из которого могут быть извлечены значимые цифры.

Это регулярное выражение также предотвращает сопоставление нулей с заполнением слева, которое JavaScript иногда принимает, но которое, как я видел, вызывает проблемы и которое ничего не добавляет к значимым цифрам, поэтому я рассматриваю предотвращение нулей с заполнением слева как преимущество (особенно в формах).Тем не менее, я уверен, что регулярное выражение можно было бы изменить, чтобы оно поглощало нули с дополнением слева.

Еще одна проблема, которую я вижу с этим регулярным выражением, заключается в том, что оно не будет совпадать 90.e9 или другие подобные числа.Тем не менее, я нахожу это или подобные совпадения крайне маловероятными, поскольку в научной нотации принято избегать таких чисел.Хотя вы можете ввести его в JavaScript, вы можете так же легко ввести 9.0e10 и добиться таких же значительных показателей.

Обновить

В ходе моего тестирования я также обнаружил ошибку, которой это могло соответствовать '.'.Таким образом, прогноз на будущее должен быть изменен следующим образом (?=\.\d|\d) что приводит к окончательному регулярному выражению:

/^[+\-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/

Вот некоторый Perl-код, который я быстро взломал.

my($sign,$coeffl,$coeffr,$exp) = $str =~ /^\s*([-+])?(\d+)(\.\d*)?e([-+]?\d+)\s*$/;

my $shift = length $coeffl;
$shift = 0 if $shift == 1;

my $coeff =
  substr( $coeffl, 0, 1 );

if( $shift || $coeffr ){
  $coeff .=
    '.'.
    substr( $coeffl, 1 );
}

$coeff .= substr( $coeffr, 1 ) if $coeffr;

$coeff = $sign . $coeff if $sign;

$exp += $shift;

say "coeff: $coeff exponent: $exp";
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top