Подтвердить что ты не робот

Размышление о научной нотации разумно?

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

У коллеги есть часть пути решения, использующего 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, и его можно найти в моем weblog.

4b9b3361

Ответ 1

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

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

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

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

alt text http://www.json.org/number.gif

Если вы посмотрите на строку 456 своего json2.js script (безопасное преобразование в/из 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)

Удачи!

Ответ 2

Вот код 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";

Ответ 3

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

Это дает следующие преимущества:

  1. позволяет сопоставлять числа, такие как .9 (я сделал .9 ((?:0|[1-9]\d*) с ?)
  2. предотвращает совпадение только оператора в начале и предотвращает совпадение строк нулевой длины (использует lookahead, (?=.))
  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+)?$/