Pergunta

Eu quero ser capaz de escrever uma função que recebe um número em notação científica como uma string e divide fora dele, o coeficiente eo expoente como itens separados. Eu poderia simplesmente usar uma expressão regular, mas o número de entrada não pode ser normalizado e eu prefiro ser capaz de normalizar e, em seguida, quebrar as peças para fora.

Um colega tem forma parte de uma solução usando VB6, mas não é muito lá, como a transcrição abaixo shows.

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

deveria ter sido 1 e 6

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

correta

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

correta

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

deve ser -1,233456 e -2

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

correta

Todas as idéias? By the way, Clive é um CLI com base em VBScript e pode ser encontrado no meu weblog .

Foi útil?

Solução

Google em "notação científica expressões regulares" mostra uma série de partidas, incluindo esta ( não usá-lo !!!! ), que utiliza

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

que inclui casos como -.5e7 e + 00000e33 (ambos os quais você não pode querer permitir).

Em vez disso, gostaria de altamente recomendamos que você use a sintaxe on site JSON de Doug Crockford , que documenta de forma explícita o que constitui um número em JSON. Aqui está o diagrama de sintaxe correspondente tomadas a partir dessa página:

text alt
(fonte: json.org )

Se você olhar na linha 456 do seu json2.js roteiro (conversão segura de / para JSON em javascript), você verá esta parte de uma expressão regular:

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

que, ironicamente, não coincide com o seu diagrama de sintaxe .... (parece que eu deveria registrar um bug) Eu acredito que uma expressão regular que faz implementar esse diagrama de sintaxe é esta:

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

e se você quiser permitir que uma inicial + bem, você obtém:

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

Adicionar captura de parênteses ao seu gosto.

Eu também recomendo que você carne para fora um monte de casos de teste, para garantir que você incluir essas possibilidades que deseja incluir (ou não incluir), tais como:

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

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

Boa sorte!

Outras dicas

Construindo fora da resposta mais bem cotados, eu modifiquei a regex ligeiramente para ser /^[+\-]?(?=.)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/.

Os benefícios deste oferece são:

  1. permite que números como .9 correspondência (I fez o opcional (?:0|[1-9]\d*) com ?)
  2. impede correspondentes apenas o operador no inicio e impede correspondentes cadeias de comprimento zero (usos lookAhead, (?=.))
  3. impede correspondentes e9 porque requer a \d antes da notação científica

Meu objetivo neste é usá-lo para capturar figuras significativas e fazer matemática significativa. Então eu também vou cortá-lo com a captura de grupos assim: /^[+\-]?(?=.)(0|[1-9]\d*)?(\.\d*)?(?:(\d)[eE][+\-]?\d+)?$/

.

Uma explicação de como obter números significativos a partir deste:

  1. Toda a captura é o número que você pode entregar a parseFloat()
  2. Jogos 1-3 irá aparecer como indefinido ou cordas, de modo combinando-as (substituir undefined é com '') deve dar o número original a partir do qual números significativos pode ser extraída.

Este regex também impede correspondência zeros à esquerda acolchoado, que JavaScript às vezes aceita, mas que eu já vi questões de causa e que não acrescenta nada à algarismos significativos, então eu ver prevenir zeros à esquerda acolchoado como um benefício (especialmente em formas). No entanto, tenho certeza que o regex poderia ser modificado para devorar zeros à esquerda-acolchoado.

Outro problema que vejo com este regex é que não vai corresponder 90.e9 ou outros tais números. No entanto, acho que este ou semelhantes partidas altamente improvável, uma vez que é a convenção em notação científica para evitar tais números. Embora você possa inseri-lo em JavaScript, você pode apenas como facilmente entrar 9.0e10 e alcançar os mesmos algarismos significativos.

Atualizar

Em meus testes, eu também pego o erro que poderia corresponder '.'. Assim, o look-ahead deve ser modificado para (?=\.\d|\d) que leva à regex final:

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

Aqui está um código Perl eu só cortei juntos rapidamente.

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";
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top