سؤال

System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);

صحيح.

أدرك أن العدد الصحيح في Java هو 32 بت ولا يمكن أن يتجاوز 231-1، لكن لا أستطيع أن أفهم سبب إضافة 1 إليه MAX_VALUE النتائج في MIN_VALUE وليس في نوع من الاستثناء.دون ذكر شيء مثل التحويل الشفاف إلى نوع أكبر، كما تفعل روبي.

هل هذا السلوك محدد في مكان ما؟هل يمكنني الاعتماد عليه؟

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

المحلول

لأن العدد الصحيح يفيض.عندما يفيض، القيمة التالية هي Integer.MIN_VALUE. JLS ذات الصلة

إذا تجاوزت إضافة عدد صحيح، فإن النتيجة هي البتات ذات الترتيب المنخفض من المجموع الرياضي كما هو ممثل في تنسيق ثنائي كبير بما فيه الكفاية.في حالة حدوث تجاوز، فإن إشارة النتيجة ليست هي نفس إشارة المجموع الرياضي لقيمتي المعاملين.

نصائح أخرى

يتم تجاوز سعة تخزين الأعداد الصحيحة و لم تتم الإشارة إلى ذلك بأي شكل من الأشكال، كما هو مذكور في JSL 3rd Ed.:

لا تشير عوامل التشغيل الصحيحة المضمنة إلى تجاوز السعة أو تجاوز السعة بأي شكل من الأشكال.يمكن لمشغلي الأعداد الصحيحة رمي NullPointerException إذا فتح التحويل (§5.1.8) مطلوب مرجع فارغ.بخلاف ذلك، مشغلي الأعداد الصحيحة الوحيدون الذين يمكنهم طرح استثناء (§11) هي عامل تقسيم الأعداد الصحيحة / (§15.17.2) ومشغل العدد الصحيح المتبقي % (§15.17.3), ، والتي رمي ArithmeticException إذا كان المعامل الأيمن هو صفر، وعوامل الزيادة والنقصان ++(§15.15.1, §15.15.2) و --(§15.14.3, §15.14.2)، والتي يمكن أن ترمي OutOfMemoryError إذا الملاكمة التحويل (§5.1.7) مطلوب ولا توجد ذاكرة كافية لإجراء التحويل.

مثال في تخزين 4 بت:

MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)

MAX_INT + 1:

 0111+
 0001
 ----
 1000

يجب أن تفهم كيفية تمثيل القيم الصحيحة في شكل ثنائي، وكيف تعمل عملية الجمع الثنائي.تستخدم Java تمثيلاً يسمى مكمل الاثنين، حيث يمثل البت الأول من الرقم علامته.عندما تضيف 1 إلى أكبر عدد صحيح في Java، والذي يحتوي على علامة بت تساوي 0، تصبح علامة البت الخاصة به 1 ويصبح الرقم سالبًا.

وهذا الرابط يشرح بمزيد من التفاصيل: http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-Java

--

تتعامل مواصفات لغة Java مع هذا السلوك هنا: http://docs.Oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

إذا تجاوزت إضافة عدد صحيح، فإن النتيجة هي البتات ذات الترتيب المنخفض من المجموع الرياضي كما هو ممثل في تنسيق ثنائي كبير بما فيه الكفاية.في حالة حدوث تجاوز، فإن إشارة النتيجة ليست هي نفس إشارة المجموع الرياضي لقيمتي المعاملين.

مما يعني أنه يمكنك الاعتماد على هذا السلوك.

في معظم المعالجات، لا تحتوي التعليمات الحسابية على أي وضع للخطأ عند تجاوز السعة.لقد وضعوا علامة يجب التحقق منها.هذه تعليمات إضافية لذا ربما تكون أبطأ.لكي تكون عمليات تنفيذ اللغة سريعة قدر الإمكان، يتم تحديد اللغات بشكل متكرر لتجاهل الخطأ والمتابعة.بالنسبة لـ Java، يتم تحديد السلوك في ملف JLS.بالنسبة للغة C، لا تحدد اللغة السلوك، لكن المعالجات الحديثة ستعمل مثل Java.

أعتقد أن هناك مقترحات لمكتبات Java SE 8 (المحرجة) للتخلص من السعة، بالإضافة إلى العمليات غير الموقعة.أعتقد أن السلوك الشائع في عالم DSP هو تثبيت القيم عند الحد الأقصى Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [ليس جافا].

أنا متأكد من أن اللغات المستقبلية ستستخدم دقة عشوائية، ولكن ليس لفترة من الوقت بعد.يتطلب تصميم مترجم أكثر تكلفة للتشغيل بسرعة.

نفس السبب وراء تغير التاريخ عند عبور خط التاريخ الدولي:هناك انقطاع هناك.إنها مدمجة في طبيعة الإضافة الثنائية.

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

عندما تضيف 3 (في ثنائي 11) إلى 1 (في ثنائي 1)، يجب عليك التغيير إلى 0 (في ثنائي 0) كل ثنائي 1 بدءًا من اليمين، حتى تحصل على 0، والذي يجب عليك التغيير إليه 1. Integer.MAX_VALUE وقد امتلأت جميع الأماكن 1 لذلك يبقى هناك فقط 0س.

يحدث تجاوز السعة وعدد الطبيعة المتوافق مع اثنين في "الحلقة الثانية"، وكنا في أقصى الموضع الأيمن 2147483647 وبعد جمع 1، ظهرنا في أقصى الموضع الأيسر -2147483648، والزيادة التالية تذهب -2147483647، -2147483646، -2147483645، ...وهكذا إلى أقصى اليمين مرارًا وتكرارًا، طبيعة آلة الجمع على هذا العمق.

بعض الأمثلة:

int a = 2147483647;

System.out.println(a);

يعطي:2147483647

System.out.println(a+1);

يعطي:-2147483648 (لأن التجاوز والعدد الطبيعي المتوافق مع اثنين يستمر في "الحلقة الثانية"، كنا في أقصى الموضع الأيمن 2147483647 وبعد جمع 1، ظهرنا في أقصى الموضع الأيسر -2147483648، والزيادة التالية تذهب -2147483648، -2147483647، -2147483646، ...وهكذا تتقدم إلى أقصى اليمين مرارًا وتكرارًا، طبيعة آلة الجمع على عمق البت هذا)

System.out.println(2-a); 

يعطي: -2147483645 (-2147483647+2 يبدو منطقيًا رياضيًا)

System.out.println(-2-a);

يعطي:2147483647 (-2147483647-1 -> -2147483648، -2147483648-1 -> 2147483647 بعض الحلقات الموضحة في الإجابات السابقة)

System.out.println(2*a);

يعطي:-2 (2147483647+2147483647 -> -2147483648+2147483646 مرة أخرى منطقي رياضي)

System.out.println(4*a);

يعطي:-4 (2147483647+2147483647+2147483647+2147483647 -> -2147483648+2147483646+2147483647+2147483647 -> -2-2 (حسب الإجابة الأخيرة) -> -4)`

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