ما هي أفضل طريقة لتحويل النقطة العائمة إلى عدد صحيح في JavaScript؟

StackOverflow https://stackoverflow.com/questions/131406

  •  02-07-2019
  •  | 
  •  

سؤال

هناك عدة طرق مختلفة لتحويل أرقام الفاصلة العائمة إلى أعداد صحيحة في JavaScript.سؤالي هو ما هي الطريقة التي توفر أفضل أداء، أو الأكثر توافقًا، أو التي تعتبر أفضل ممارسة؟

فيما يلي بعض الطرق التي أعرفها:

var a = 2.5;
window.parseInt(a); // 2
Math.floor(a);      // 2
a | 0;              // 2

أنا متأكد من أن هناك آخرين هناك.اقتراحات؟

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

المحلول

وفق هذا الموقع:

يتم استخدام parseInt أحيانًا كوسيلة لتحويل رقم الفاصلة العائمة إلى عدد صحيح.إنها غير مناسبة لهذه المهمة لأنه إذا كانت وسيطتها من النوع الرقمي فسيتم تحويلها أولاً إلى سلسلة ثم تحليلها كرقم...

لتقريب الأرقام إلى أعداد صحيحة، يُفضل استخدام أحد Math.round وMath.ceil وMath.floor...

نصائح أخرى

من "جافا سكريبت:الأجزاء الجيدة" من دوجلاس كروكفورد:

Number.prototype.integer = function () {
    return Math[this < 0 ? 'ceil' : 'floor'](this);
}

عند القيام بذلك، تقوم بإضافة طريقة إلى كل كائن رقم.

ثم يمكنك استخدامه مثل هذا:

var x = 1.2, y = -1.2;

x.integer(); // 1
y.integer(); // -1

(-10 / 3).integer(); // -3

من الواضح أن طريقة bitwise-not المزدوجة هي أسرع طريقة لتحديد رقم:

var x = 2.5;
console.log(~~x); // 2

اعتاد أن يكون مقالًا هنا، والآن يحصل على 404 بالرغم من ذلك: http://james.padolsey.com/javascript/double-bitwise-not/

قامت Google بتخزينها مؤقتًا: http://74.125.155.132/search?q=cache:wpZnhsbJGt0J:james.padolsey.com/javascript/double-bitwise-not/+double+bitwise+not&cd=1&hl=en&ct=clnk&gl=us

لكن آلة Wayback. تنقذ اليوم! http://web.archive.org/web/20100422040551/http://james.padolsey.com/javascript/double-bitwise-not/

لقد تم تقديم الإجابة بالفعل ولكن فقط للتوضيح.

استخدم مكتبة الرياضيات لهذا الغرض.وظائف مستديرة أو سقفية أو أرضية.

parseInt مخصص لتحويل سلسلة إلى int وهو ليس ما هو مطلوب هنا

toFixed مخصص لتحويل تعويم إلى سلسلة وليس ما هو مطلوب هنا أيضًا

نظرًا لأن وظائف Math لن تقوم بأي تحويلات من وإلى سلسلة ما، فستكون أسرع من أي من الاختيارات الأخرى الخاطئة على أي حال.

يمكنك استخدام Number(a).toFixed(0);

أو حتى مجرد a.toFixed(0);

يحرر:

هذا هو التقريب إلى 0 مكان، وهو يختلف قليلاً عن الاقتطاع، وكما اقترح شخص آخر، تُرجع toFixed سلسلة، وليس عددًا صحيحًا خامًا.مفيدة لأغراض العرض.

var num = 2.7;  // typeof num is "Number"
num.toFixed(0) == "3"

أفضل طريقة يعتمد على على:

  • وضع التقريب:ماذا نوع التقريب (من التعويم إلى عدد صحيح) تتوقعه/تطلبه
    للأرقام الموجبة و/أو السالبة التي تحتوي على جزء كسري.
    أمثلة شائعة:
    float | trunc | floor |  ceil | near (half up)
    ------+-------+-------+-------+---------------
    +∞    |   +∞  |   +∞  |   +∞  |   +∞  
    +2.75 |   +2  |   +2  |   +3  |   +3
    +2.5  |   +2  |   +2  |   +3  |   +3
    +2.25 |   +2  |   +2  |   +3  |   +2
    +0    |   +0  |   +0  |   +0  |   +0
     NaN  |  NaN  |  NaN  |  NaN  |  NaN
    -0    |   -0  |   -0  |   -0  |   -0
    -2.25 |   -2  |   -3  |   -2  |   -2
    -2.5  |   -2  |   -3  |   -2  |   -2
    -2.75 |   -2  |   -3  |   -2  |   -3
    -∞    |   -∞  |   -∞  |   -∞  |   -∞  
    
    للتحويلات من تعويم إلى عدد صحيح نحن عادة يتوقع "اقتطاع"
    (الملقب ب "الجولة نحو الصفر" الملقب ب "جولة بعيدا عن اللانهاية").
    على نحو فعال، يؤدي هذا إلى "قطع" الجزء الكسري من رقم الفاصلة العائمة.
    تتصرف معظم التقنيات والأساليب (داخليًا) بهذه الطريقة.
  • مدخل:كيف يتم تمثيل رقمك (النقطة العائمة):
    • String
      الجذر/القاعدة الشائعة:10 (عشري)
    • النقطة العائمة ("الداخلية") Number
  • انتاج:ماذا تريد أن تفعل بالقيمة الناتجة:
    • (متوسط) الإخراج String (الجذر الافتراضي 10) (على الشاشة)
    • إجراء المزيد من الحسابات على القيمة الناتجة
  • يتراوح:
    في أي نطاق رقمي تتوقع نتائج الإدخال/الحساب
    ولأي نطاق تتوقع الإخراج "الصحيح" المقابل.

فقط بعد تمت الإجابة على هذه الاعتبارات ويمكننا التفكير في الطريقة (الطرق) المناسبة والسرعة!


وفقًا لمواصفات ECMAScript 262: الجميع أرقام (نوع Number) في جافا سكريبت يتم تمثيلها/تخزينها في:
"IEEE 754 النقطة العائمة ذات الدقة المزدوجة (binary64)" شكل.
هكذا تكون الأعداد الصحيحة أيضًا الممثلة في نفس تنسيق النقطة العائمة (كأرقام بدون كسر).
ملحوظة:معظم التطبيقات يفعل استخدم أنواعًا صحيحة أكثر كفاءة (للسرعة وحجم الذاكرة). داخليا عندما يكون ذلك ممكنا!

نظرًا لأن هذا التنسيق يخزن بت إشارة واحدة و11 بتًا أسيًا وأول 53 بتًا مهمًا ("الجزء العشري")، فيمكننا أن نقول ما يلي: فقط Number-قيم بين -252 و +252 يمكن أن يكون لها جزء.
بعبارة أخرى: الجميع يمكن تمثيلها الإيجابية والسلبية Number-قيم بين 252 في الغالب) 2(211/2=1024) (عند هذه النقطة يستدعي التنسيق ذلك يوم Infinity) هي بالفعل أعداد صحيحة (مقربة داخليًا، حيث لا توجد بتات متبقية لتمثيل الأرقام الصحيحة الكسرية و/أو الأقل أهمية).

وهناك "مسكتك" الأولى:
لا يمكنك التحكم في وضع التقريب الداخلي Number-نتائج التحويلات الحرفية/السلسلة المضمنة (وضع التقريب:IEEE 754-2008 "التقريب إلى الأقرب، العلاقات إلى الزوجي") والعمليات الحسابية المضمنة (وضع التقريب:IEEE 754-2008 "التقريب إلى الأقرب").
على سبيل المثال:
252+0.25 = 4503599627370496.25 يتم تقريبها وتخزينها على النحو التالي: 4503599627370496
252+0.50 = 4503599627370496.50 يتم تقريبها وتخزينها على النحو التالي: 4503599627370496
252+0.75 = 4503599627370496.75 يتم تقريبها وتخزينها على النحو التالي: 4503599627370497
252+1.25 = 4503599627370497.25 يتم تقريبها وتخزينها على النحو التالي: 4503599627370497
252+1.50 = 4503599627370497.50 يتم تقريبها وتخزينها على النحو التالي: 4503599627370498
252+1.75 = 4503599627370497.75 يتم تقريبها وتخزينها على النحو التالي: 4503599627370498
252+2.50 = 4503599627370498.50 يتم تقريبها وتخزينها على النحو التالي: 4503599627370498
252+3.50 = 4503599627370499.50 يتم تقريبها وتخزينها على النحو التالي: 4503599627370500

للتحكم في تقريب الخاص بك Number يحتاج إلى جزء كسري (وبت واحد على الأقل لتمثيل ذلك)، وإلا فإن ceil/floor/trunc/near يُرجع العدد الصحيح الذي أدخلته فيه.

لتحديد سقف/أرضية/اقتطاع رقم يصل إلى x رقم (أرقام) عشرية كسرية كبيرة بشكل صحيح، فإننا نهتم فقط إذا كانت القيمة الكسرية العشرية الأدنى والأعلى المقابلة ستظل تعطينا قيمة كسرية ثنائية بعد التقريب (وبالتالي لا يتم السقف أو الحد الأدنى إلى العدد الصحيح التالي).
لذا، على سبيل المثال، إذا كنت تتوقع التقريب "الصحيح" (للسقف/الأرضية/الجذع) حتى رقم عشري كسري واحد مهم (x.1 to x.9)، نحن نحتاج على الأقل 3 بتات (وليس 4) لتعطينا أ القيمة الكسرية الثنائية:
0.1 هو أقرب إلى 1/(23=8)=0.125 مما هو عليه 0 و 0.9 هو أقرب إلى 1-1/(23=8)=0.875 مما هو عليه 1.

فقط يصل إلى ±2(53-3=50) هل ستحتوي جميع القيم القابلة للتمثيل على جزء ثنائي غير صفري لا يزيد عن أولاً رقم كسري عشري كبير (القيم x.1 ل x.9).
لمدة 2 الكسور العشرية ±2(53-6=47), ، لمدة 3 أعداد عشرية ±2(53-9=44), ، لأربعة أعداد عشرية ±2(53-13=40), ، لمدة 5 أعداد عشرية ±2(53-16=37), ، لمدة 6 أعداد عشرية ±2(53-19=34), ، لـ 7 أعداد عشرية ±2(53-23=30), ، لـ 8 أعداد عشرية ±2(53-26=27), ، لمدة 9 الكسور العشرية ±2(53-29=24), ، لمدة 10 الكسور العشرية ±2(53-33=20), ، لـ 11 رقمًا عشريًا ±2(53-36=17), ، إلخ..

أ "عدد صحيح آمن" في جافا سكريبت هو عدد صحيح:

  • يمكن أن يكون بالضبط ممثلة كرقم مزدوج الدقة IEEE-754، و
  • الذي تمثيل IEEE-754 لا تستطيع يكون نتيجة تقريب أي عدد صحيح آخر ليناسب تمثيل IEEE-754
    (بالرغم من ±253 (كقوة دقيقة لـ 2) يمكن تمثيلها تمامًا، فهي كذلك لا عدد صحيح آمن لأنه كان من الممكن أن يكون أيضًا ±(253+1) قبل أن يتم تقريبها لتناسب الحد الأقصى البالغ 53 بت الأكثر أهمية).

يحدد هذا بشكل فعال نطاق مجموعة فرعية من الأعداد الصحيحة (التي يمكن تمثيلها بشكل آمن). بين -253 و +253:

  • من: -(253 - 1) = -9007199254740991 (شامل)
    (ثابت يتم توفيره كخاصية ثابتة Number.MIN_SAFE_INTEGER منذ ES6)
  • ل: +(253 - 1) = +9007199254740991 (شامل)
    (ثابت يتم توفيره كخاصية ثابتة Number.MAX_SAFE_INTEGER منذ ES6)
    polyfill تافهة لهذه الثوابت ES6 الجديدة:

    Number.MIN_SAFE_INTEGER || (Number.MIN_SAFE_INTEGER=
      -(Number.MAX_SAFE_INTEGER=9007199254740991) //Math.pow(2,53)-1
    );
    


منذ ES6 هناك أيضًا طريقة ثابتة مجانية Number.isSafeInteger() الذي يختبر ما إذا كانت القيمة التي تم تمريرها من النوع Number وهو عدد صحيح ضمن نطاق الأعداد الصحيحة الآمنة (إرجاع قيمة منطقية true أو false).
ملحوظة:سوف يعود أيضا false ل: NaN, Infinity ومن الواضح String (حتى لو كان يمثل رقماً).
بوليفيل مثال:

Number.isSafeInteger || (Number.isSafeInteger = function(value){
  return typeof value === 'number' && 
                value === Math.floor(value) &&
                value  <   9007199254740992 &&
                value  >  -9007199254740992;
});

يوفر ECMAScript 2015 / ES6 طريقة ثابتة جديدة Math.trunc()
لاقتطاع تعويم إلى عدد صحيح:

إرجاع الجزء المتكامل من الرقم x، مع إزالة أي أرقام كسرية.إذا كان x عددًا صحيحًا بالفعل، فإن النتيجة هي x.

أو أبسط (MDN):

على عكس طرق الرياضيات الثلاثة الأخرى: Math.floor(), Math.ceil() و Math.round(), ، الطريقة Math.trunc() العمل بسيط جدًا ومباشر:
ما عليك سوى اقتطاع النقطة والأرقام الموجودة خلفها، بغض النظر عما إذا كانت الوسيطة رقمًا موجبًا أو رقمًا سالبًا.

يمكننا أن نوضح أكثر (و polyfill) Math.trunc() كما:

Math.trunc || (Math.trunc = function(n){
    return n < 0 ? Math.ceil(n) : Math.floor(n); 
});

لاحظ أن حمولة polyfill أعلاه يمكن أن تكون كذلك يحتمل يتم تحسينه مسبقًا بشكل أفضل بواسطة المحرك مقارنة بـ:
Math[n < 0 ? 'ceil' : 'floor'](n);

الاستخدام: Math.trunc(/* Number or String */)
مدخل:(عدد صحيح أو نقطة عائمة) Number (ولكن سيحاول بكل سرور تحويل سلسلة إلى رقم)
انتاج |:(عدد صحيح) Number (لكننا سنحاول بكل سرور تحويل الرقم إلى سلسلة في سياق سلسلة)
يتراوح: -2^52 ل +2^52 (أبعد من ذلك يجب أن نتوقع "أخطاء التقريب" (وفي مرحلة ما التدوين العلمي/الأسي) بشكل واضح وببساطة لأن لدينا Number المدخلات في IEEE 754 فقدت بالفعل الدقة الكسرية:منذ الأرقام بين ±2^52 ل ±2^53 كلهم جاهزين مدورة داخليا الأعداد الصحيحة (على سبيل المثال 4503599627370509.5 يتم تمثيله داخليًا بالفعل كـ 4503599627370510) وما بعدها ±2^53 الأعداد الصحيحة تفقد أيضًا الدقة (قوى 2)).


تعويم لتحويل عدد صحيح عن طريق طرح بقية (%) من قسم بواسطة 1:

مثال: result = n-n%1 (أو n-=n%1)
وينبغي لهذا أيضا اقتطاع يطفو.نظرًا لأن عامل الباقي لديه قيمة أعلى الأولوية من الطرح نحصل بشكل فعال على: (n)-(n%1).
بالنسبة للأرقام الموجبة، من السهل أن ترى أن هذه القيمة تساوي القيمة: (2.5) - (0.5) = 2,
بالنسبة للأرقام السالبة، فإن هذا يسقف القيمة: (-2.5) - (-0.5) = -2 (لأن --=+ لذا (-2.5) + (0.5) = -2).

منذ مدخل و انتاج نكون Number نحن يجب احصل على ال نفس النطاق المفيد والإخراج مقارنة بـES6 Math.trunc() (أو هو بوليفيل).
ملحوظة:صعبة أنا يخاف (غير متأكد) قد تكون هناك اختلافات:نظرًا لأننا نجري عمليات حسابية (والتي تستخدم داخليًا وضع التقريب "nearTiesEven" (المعروف أيضًا باسم Banker's Rounding)) على الرقم الأصلي (الرقم العائم) والرقم المشتق الثاني (الكسر) يبدو أن هذا يدعو إلى تفاقم أخطاء التمثيل الرقمي والتقريب الحسابي، وبالتالي من المحتمل عودة تعويم بعد كل شيء..


تعويم لتحويل عدد صحيح عن طريق (ab-) باستخدام عمليات البت:

يعمل هذا من خلال داخليا إجبار (النقطة العائمة) Number التحويل (الاقتطاع والتجاوز) إلى قيمة عددية 32 بت موقعة (تكملة اثنين) باستخدام عملية bitwise على Number (ويتم تحويل النتيجة مرة أخرى إلى (نقطة عائمة) Number الذي يحمل فقط قيمة العدد الصحيح).

مرة أخرى، مدخل و انتاج يكون Number (ومرة أخرى التحويل الصامت من إدخال السلسلة إلى الرقم وإخراج الرقم إلى السلسلة).

والأهم من ذلك أنه صعب (وعادة ما يُنسى ولا يتم شرحه):
اعتمادًا على عملية البت وعلامة الرقم, ، ال مفيد يتراوح سوف يكون محدود بين:
-2^31 ل +2^31 (يحب ~~num أو num|0 أو num>>0) أو 0 ل +2^32 (num>>>0).

وينبغي توضيح ذلك بشكل أكبر من خلال جدول البحث التالي (الذي يحتوي على الجميع أمثلة "حرجة":

              n             | n>>0 OR n<<0 OR   |    n>>>0    | n < 0 ? -(-n>>>0) : n>>>0
                            | n|0 OR n^0 OR ~~n |             |
                            | OR n&0xffffffff   |             |
----------------------------+-------------------+-------------+---------------------------
+4294967298.5 = (+2^32)+2.5 |             +2    |          +2 |          +2
+4294967297.5 = (+2^32)+1.5 |             +1    |          +1 |          +1
+4294967296.5 = (+2^32)+0.5 |              0    |           0 |           0
+4294967296   = (+2^32)     |              0    |           0 |           0
+4294967295.5 = (+2^32)-0.5 |             -1    | +4294967295 | +4294967295
+4294967294.5 = (+2^32)-1.5 |             -2    | +4294967294 | +4294967294
       etc...               |         etc...    |      etc... |      etc...
+2147483649.5 = (+2^31)+1.5 |    -2147483647    | +2147483649 | +2147483649
+2147483648.5 = (+2^31)+0.5 |    -2147483648    | +2147483648 | +2147483648
+2147483648   = (+2^31)     |    -2147483648    | +2147483648 | +2147483648
+2147483647.5 = (+2^31)-0.5 |    +2147483647    | +2147483647 | +2147483647
+2147483646.5 = (+2^31)-1.5 |    +2147483646    | +2147483646 | +2147483646
       etc...               |         etc...    |      etc... |      etc...
         +1.5               |             +1    |          +1 |          +1
         +0.5               |              0    |           0 |           0
          0                 |              0    |           0 |           0
         -0.5               |              0    |           0 |           0
         -1.5               |             -1    | +4294967295 |          -1
       etc...               |         etc...    |      etc... |      etc...
-2147483646.5 = (-2^31)+1.5 |    -2147483646    | +2147483650 | -2147483646
-2147483647.5 = (-2^31)+0.5 |    -2147483647    | +2147483649 | -2147483647
-2147483648   = (-2^31)     |    -2147483648    | +2147483648 | -2147483648
-2147483648.5 = (-2^31)-0.5 |    -2147483648    | +2147483648 | -2147483648
-2147483649.5 = (-2^31)-1.5 |    +2147483647    | +2147483647 | -2147483649
-2147483650.5 = (-2^31)-2.5 |    +2147483646    | +2147483646 | -2147483650
       etc...               |         etc...    |      etc... |      etc...
-4294967294.5 = (-2^32)+1.5 |             +2    |          +2 | -4294967294
-4294967295.5 = (-2^32)+0.5 |             +1    |          +1 | -4294967295
-4294967296   = (-2^32)     |              0    |           0 |           0
-4294967296.5 = (-2^32)-0.5 |              0    |           0 |           0
-4294967297.5 = (-2^32)-1.5 |             -1    | +4294967295 |          -1
-4294967298.5 = (-2^32)-2.5 |             -2    | +4294967294 |          -2

ملاحظة 1:العمود الأخير له نطاق موسع 0 ل -4294967295 استخدام (n < 0 ? -(-n>>>0) : n>>>0).
ملاحظة 2:يقدم bitwise حمل التحويل الخاص به (س) (الشدة مقابل Math يعتمد على التنفيذ الفعلي، لذلك bitwise استطاع يكون أسرع (غالبًا في المتصفحات القديمة القديمة)).


من الواضح أنه إذا كان رقم "النقطة العائمة" الخاص بك هو String لنبدء ب،
parseInt(/*String*/, /*Radix*/) سيكون خيارًا مناسبًا لتحليله إلى عدد صحيح Number.
parseInt() سوف اقتطاع كذلك (للأرقام الإيجابية والسلبية).
ال يتراوح يقتصر مرة أخرى على النقطة العائمة ذات الدقة المزدوجة IEEE 754 كما هو موضح أعلاه Math طُرق).

وأخيرا، إذا كان لديك String وتوقع أ String كإخراج، يمكنك أيضًا تقطيع نقطة الجذر والكسر (مما يمنحك أيضًا نطاق اقتطاع دقيق أكبر مقارنة بنقطة IEEE 754 العائمة ذات الدقة المزدوجة (±2^52))!


إضافي:
من المعلومات المذكورة أعلاه يجب أن يكون لديك الآن كل ما تحتاج إلى معرفته.

إذا كنت تريد على سبيل المثال جولة بعيدا عن الصفر (الملقب ب جولة نحو اللانهاية) يمكنك تعديل Math.trunc() بوليفيل، ل مثال:

Math.intToInf || (Math.intToInf = function(n){
    return n < 0 ? Math.floor(n) : Math.ceil(n); 
});
var i = parseInt(n, 10);

إذا لم تحدد قيم الجذر مثل '010' سيتم التعامل معها على أنها ثماني (وبالتالي ستكون النتيجة 8 لا 10).

استخدام عوامل تشغيل bitwise.قد لا تكون هذه هي الطريقة الأوضح للتحويل إلى عدد صحيح، ولكنها تعمل على أي نوع من أنواع البيانات.

لنفترض أن وظيفتك تأخذ وسيطة value, ، وتعمل الوظيفة بهذه الطريقة value يجب أن يكون دائمًا عددًا صحيحًا (ويُقبل 0).ثم سيتم تعيين أي مما يلي value كعدد صحيح:

value = ~~(value)
value = value | 0;
value = value & 0xFF;   // one byte; use this if you want to limit the integer to
                        // a predefined number of bits/bytes

أفضل ما في الأمر هو أن هذا يعمل مع سلاسل (ما قد تحصل عليه من إدخال النص، وما إلى ذلك) وهي عبارة عن أرقام ~~("123.45") === 123.أي قيم غير رقمية تؤدي إلى 0, ، أي،

~~(undefined) === 0
~~(NaN) === 0
~~("ABC") === 0

إنه يعمل مع الأرقام السداسية العشرية كسلاسل (مع ملف 0x بادئة)

~~("0xAF") === 175

أعتقد أن هناك نوعًا من الإكراه.سأجري بعض اختبارات الأداء للمقارنة بينها parseInt() و Math.floor(), ، لكني أحب الحصول على الراحة الإضافية المتمثلة في لا Errors يتم رميها والحصول على 0 لغير الارقام

لذلك قمت بوضع معيار، على Chrome عندما يكون الإدخال رقمًا بالفعل، سيكون الأسرع ~~num و num|0, ، نصف السرعة: Math.floor, ، وسيكون الأبطأ parseInt يرى هنا

benchmark result

يحرر:يبدو أن هناك بالفعل شخص آخر قام بذلك التقريب المعيار (مزيد من النتيجة) وإضافية طرق: num>>0 (بسرعة مثل |0) و num - num%1 (أحيانا سريعا)

يبدو أن السؤال يطرح على وجه التحديد حول التحويل من عدد عشري إلى عدد صحيح.ما أفهمه هو أن طريقة القيام بذلك هي الاستخدام toFixed.لذا...

var myFloat = 2.5;
var myInt = myFloat.toFixed(0);

هل يعرف أحد إذا Math.floor() أكثر أو أقل أداء من Number.toFixed()?

يمكنك أيضًا القيام بذلك بهذه الطريقة:

var string = '1';
var integer = a * 1;

من المحتمل أن يكون parseInt() هو الأفضل. a | 0 لا يفعل ما تريده حقًا (إنه يعين 0 فقط إذا كانت a قيمة غير محددة أو فارغة، وهو ما يعني أن كائنًا أو مصفوفة فارغة تجتاز الاختبار)، ويعمل Math.floor من خلال نوع من الخداع (يستدعي بشكل أساسي parseInt()) في الخلفية).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top