Domanda

Voglio essere in grado di scrivere una funzione che riceve un numero in notazione scientifica come una stringa e divide da esso il coefficiente e l'esponente come elementi separati. Potrei semplicemente usare un'espressione regolare, ma il numero in entrata potrebbe non essere normalizzato e preferirei essere in grado di normalizzare e quindi suddividere le parti.

Un collega ha ottenuto una soluzione parziale utilizzando VB6 ma non è del tutto lì, come mostra la trascrizione di seguito.

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

avrebbe dovuto essere 1 e 6

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

corretta

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

corretta

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

dovrebbe essere -1.233456 e -2

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

corretta

Qualche idea? A proposito, Clive è una CLI basata su VBScript e può essere trovata sul mio weblog .

Altri suggerimenti

Partendo dalla risposta con il punteggio più alto, ho modificato leggermente la regex in / ^ [+ \ -]? (? =.) (?: 0 | [1-9] \ d *)? ( ?: \ \ d *) (:.????. \ d [ee] [+ \ -] \ d +) $ /

I vantaggi che offre sono:

  1. consente numeri corrispondenti come .9 (ho reso (?: 0 | [1-9] \ d *) opzionale con ? )
  2. impedisce la corrispondenza solo dell'operatore all'inizio e impedisce la corrispondenza di stringhe di lunghezza zero (utilizza lookahead, (? =.) )
  3. impedisce la corrispondenza di e9 perché richiede il \ d prima della notazione scientifica

Il mio obiettivo in questo è di usarlo per catturare figure significative e fare calcoli significativi. Quindi lo suddivido anche in gruppi di acquisizione come questo: /^[+\-[?(?=.)(0|[1-9 lasting\d*)?(\.\d ? (?: (\ d) *) [ee] [+ \ -] \ d +) $ /

??.

Una spiegazione di come ottenere cifre significative da questo:

  1. L'intera acquisizione è il numero che puoi consegnare a parseFloat()
  2. Le corrispondenze 1-3 verranno visualizzate come non definite o come stringhe, quindi combinandole (sostituisci non definito con '' ) dovresti fornire il numero originale da cui cifre significative può essere estratto.

Questa regex impedisce anche la corrispondenza degli zeri con riempimento a sinistra, che a volte accetta JavaScript ma che ho visto causare problemi e che non aggiunge nulla a cifre significative, quindi vedo la prevenzione degli zeri con riempimento a sinistra come un vantaggio (specialmente nei moduli). Tuttavia, sono sicuro che il regex potrebbe essere modificato per inghiottire zeri con riempimento a sinistra.

Un altro problema che vedo con questo regex è che non corrisponderà a 90.e9 o ad altri numeri simili. Tuttavia, trovo altamente improbabile questo o simili abbinamenti in quanto è la convenzione nella notazione scientifica per evitare tali numeri. Sebbene sia possibile inserirlo in JavaScript, è possibile inserire facilmente 9.0e10 e ottenere le stesse cifre significative.

Aggiorna

Nei miei test, ho anche riscontrato l'errore che poteva corrispondere a '.' . Quindi il look-ahead dovrebbe essere modificato in (? = \. \ D | \ d) che porta alla regex finale:

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

Ecco un po 'di codice Perl che ho appena hackerato insieme 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";
scroll top