Analizowanie notacji naukowej sensownie?
Chcę być w stanie napisać funkcję, która otrzymuje liczbę w notacji naukowej jako ciąg i dzieli z niej Współczynnik i wykładnik jako oddzielne pozycje. Mógłbym po prostu użyć wyrażenia regularnego, ale liczba przychodząca może nie być znormalizowana i wolałbym być w stanie normalizować, a następnie rozbijać części.
Kolega ma częściowo sposób rozwiązania przy użyciu VB6, ale to nie do końca tam, jak pokazuje poniższy zapis.
cliVe> a = 1e6
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 10 exponent: 5
powinno być 1 and 6
cliVe> a = 1.1e6
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.1 exponent: 6
poprawne
cliVe> a = 123345.6e-7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: -2
poprawne
cliVe> a = -123345.6e-7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: -2
powinno być -1.233456 i -2
cliVe> a = -123345.6e+7
cliVe> ? "coeff: " & o.spt(a) & " exponent: " & o.ept(a)
coeff: 1.233456 exponent: 12
poprawne
Jakieś pomysły? Przy okazji, Clive jest CLI opartym na VBScript i można go znaleźć na moim blogu .3 answers
Google na "scientific notation regexp" pokazuje liczbę dopasowań, w tym Ten (nie używaj go!!!!), który wykorzystuje
*** warning: questionable ***
/[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/
Który obejmuje przypadki takie jak -.5e7 i + 00000e33 (oba mogą nie chcieć).
Zamiast tego, ja wysoce zalecam użycie składni na stronie Douga Crockforda JSON , która jawnie dokumentuje to, co stanowi liczbę w JSON. Oto odpowiedni schemat składni wzięty z ta strona:
Alt text http://www.json.org/number.gif
Jeśli spojrzysz na linię 456 jego json2.skrypt js (bezpieczna konwersja do / Z JSON w javascript), zobaczysz tę część wyrażenia regularnego:
/-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/
Co, jak na ironię, nie pasuje do jego diagramu składni.... (wygląda na to, że powinienem zgłosić błąd) uważam, że regexp, który implementuje ten diagram składni, to ten:
/-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/
I jeśli chcesz zezwolić na inicjał +, to get:
/[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/
Dodaj nawiasy przechwytywania do swoich upodobań.
Gorąco polecam również kilka przypadków testowych, aby upewnić się, że uwzględniasz te możliwości, które chcesz włączyć (lub nie włączyć), takie jak:
allowed:
+3
3.2e23
-4.70e+9
-.2E-4
-7.6603
not allowed:
+0003 (leading zeros)
37.e88 (dot before the e)
Powodzenia!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-18 15:07:23
Oto kod Perla, który szybko zhakowałem.
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";
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-18 04:01:56
Bazując na najwyżej ocenianej odpowiedzi, zmodyfikowałem nieco regex na /^[+\-]?(?=.)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/
.
Korzyści, jakie daje to:
- pozwala dopasować liczby takie jak
.9
(zrobiłem(?:0|[1-9]\d*)
opcjonalnie z?
) - zapobiega dopasowywaniu tylko operatora na początku i zapobiega dopasowywaniu ciągów o zerowej długości (używa lookahead,
(?=.)
) - zapobiega dopasowaniu
e9
, ponieważ wymaga\d
przed notacją naukową
Moim celem w tym jest aby użyć go do przechwytywania znaczących liczb i wykonywania znaczących obliczeń. Więc zamierzam również pokroić go z przechwytywania grup takich jak tak: /^[+\-]?(?=.)(0|[1-9]\d*)?(\.\d*)?(?:(\d)[eE][+\-]?\d+)?$/
.
Wyjaśnienie, jak uzyskać znaczące liczby z tego:
- cały uchwyt jest liczbą, którą możesz podać
parseFloat()
- dopasowania 1-3 będą wyświetlane jako undefined lub strings, więc ich połączenie (zastąp
undefined
's przez''
) powinno dać liczbę pierwotną, z której mogą być znaczące liczby / align = "left" /
Ten regex zapobiega również dopasowywaniu zer lewych, które JavaScript czasami akceptuje, ale które widziałem powodować problemy i które nie dodaje nic do znaczących liczb, więc widzę zapobieganie zer lewych jako korzyść (szczególnie w formularzach). Jednak, jestem pewien, że regex można zmodyfikować, aby pożerać lewe wyściełane zera.
Kolejny problem widzę z tym regex jest to, że nie będzie pasować 90.e9
lub inne tego typu numery. Jednak uważam, że to lub podobne pasuje bardzo mało prawdopodobne, ponieważ jest to konwencja w notacji naukowej, aby uniknąć takich liczb. Chociaż można go wprowadzić w JavaScript, można równie łatwo wprowadzić 9.0e10
i osiągnąć te same znaczące liczby.
UPDATE
W moich testach złapałem również błąd, który może pasować '.'
. Tak więc spojrzenie w przyszłość powinno być zmodyfikowane do (?=\.\d|\d)
, co prowadzi do ostatecznego wyrażenia regularnego:
/^[+\-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:\d[eE][+\-]?\d+)?$/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-10 19:47:04