سؤال

أريد أن أكون قادرًا على كتابة دالة تستقبل رقمًا بالتدوين العلمي كسلسلة وتقسم منه المعامل والأس كعناصر منفصلة.يمكنني فقط استخدام تعبير عادي، ولكن قد لا تتم تسوية الرقم الوارد وأفضل أن أكون قادرًا على التطبيع ثم تقسيم الأجزاء.

لقد حصل أحد الزملاء على جزء من الحل باستخدام 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 ويمكن العثور عليه على موقعي مدونة.

هل كانت مفيدة؟

المحلول

جوجل على "التدوين العلمي العادي" يظهر عدد من المباريات منها هذا (لا تستخدمه!!!!) الذي يستخدم

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

والتي تتضمن حالات مثل -.5e7 و+00000e33 (وهما قد لا ترغب في السماح بهما).

بدلا من ذلك، أود أن للغاية أنصحك باستخدام بناء الجملة الخاص بـ Doug Crockford موقع جيسون الذي يوثق بوضوح ما يشكل رقمًا في JSON.إليك مخطط بناء الجملة المقابل المأخوذ من تلك الصفحة:

alt text
(مصدر: json.org)

إذا نظرت إلى السطر 456 منه json2.js البرنامج النصي (التحويل الآمن من/إلى JSON في جافا سكريبت)، سترى هذا الجزء من التعبير العادي:

/-?\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. يمنع مطابقة عامل التشغيل فقط في البداية ويمنع مطابقة السلاسل ذات الطول الصفري (يستخدم 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+)?$/

وهنا بعض التعليمات البرمجية بيرل أنا فقط اخترق معا بسرعة.

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