ints طويلة في فورتران
-
13-09-2020 - |
سؤال
أحاول العمل بأعداد كبيرة (~10^14)، وأحتاج إلى أن أكون قادرًا على تخزينها وتكرارها عبر حلقات بهذا الطول، أي.
n=SOME_BIG_NUMBER
do i=n,1,-1
لقد جربت تدوين النجمة المعتاد، kind=8
إلخ.لكن يبدو أن لاشئ يعمل.ثم قمت بفحص huge
الوظيفة الجوهرية والرمز:
program inttest
print *,huge(1)
print *,huge(2)
print *,huge(4)
print *,huge(8)
print *,huge(16)
print *,huge(32)
end program inttest
ينتج الرقم 2147483647 في جميع الحالات.لماذا هذا؟أنا أستخدم gfortran (f95) على جهاز 64 بت.
إذا كنت سأحتاج إلى مكتبة كبيرة، فما هي المكتبة التي يقترحها الناس؟
المحلول
إصدارات gfortran التي أستخدمها، 4.3 و4.4 و4.5 على جهاز Mac، تدعم الأعداد الصحيحة ذات 8 بايت.أفضل طريقة لتحديد نوع متغير في Fortran >= 90 هي استخدام دالة جوهرية لتحديد الدقة التي تحتاجها.يحاول:
integer, parameter :: LargeInt_K = selected_int_kind (18)
integer (kind=LargeInt_K) :: i, n
للحصول على 18 رقمًا عشريًا على الأقل، والذي سيكون عادةً عددًا صحيحًا مكون من 8 بايت.
مع gfortran 4.3، تكون المخرجات الضخمة (1_LargeInt_K) 9223372036854775807.عندما كتبت ضخمًا (1)، وما إلى ذلك، كان الثابت افتراضيًا هو عدد صحيح افتراضي، ومن الواضح هنا أن 4 بايت منذ أن عاد ضخم 2147483647.لذلك في بعض الأحيان تحتاج إلى تحديد دقة الثوابت، وليس فقط المتغيرات - والأكثر شيوعًا أن هذا يؤدي إلى تعثر الأشخاص عندما يفقدون أرقامًا كبيرة على ثابت حقيقي، والذي يتم تعيينه افتراضيًا على دقة واحدة.
انظر أيضا فورتران:عدد صحيح * 4 مقابل عدد صحيح (4) مقابل عدد صحيح (نوع = 4)
عادةً ما يكون لـ gfortran اسم الأمر gfortran.هل يمكن أن يكون f95 مترجمًا مختلفًا؟جرب "gfortran -v" و"f95 -v".
نصائح أخرى
لقد أخطأت في فهم التعريف الدقيق لل HUGE
وظيفة. HUGE(num)
تقوم بإرجاع أكبر رقم بنفس النوع والنوع num
.القيمة التي تم إرجاعها لها أيضًا نفس النوع والنوع num
.نظرًا لأن جميع قيم الإدخال الخاصة بك هي أعداد صحيحة (افتراضية). HUGE
, بشكل صحيح، تُرجع أكبر عدد صحيح بالحجم الافتراضي.
HUGE(num)
لا يُرجع أكبر عدد صحيح مع kind=num
.ولا كذلك HUGE(num)
إرجاع أكبر عدد يمكن تمثيله في num
بايت.بينما يستخدم العديد من المترجمين integer(kind=4)
و integer(kind=8)
إلخ بالنسبة للأعداد الصحيحة ذات 4 و8 بايت، لا يضمن معيار اللغة ذلك ولا يمكن الاعتماد عليه ليكون محمولاً.
تخبرك إجابة @MSB بكيفية القيام بما تريد، أنا فقط أقدم بعض التوضيحات.
ملخص:النظر في النظر في خيارات المترجم.
لقد مر وقت طويل منذ أن قمت باستخدام لغة FORTRAN، ولا أتذكر استخدام HUGE()، لكنني نظرت إلى هذا قليلاً.يحتوي جهاز Intel Linux الخاص بي على gfortran 4.1.2.لقد وجدت أنني اضطررت إلى الترجمة مع تشغيل الخيار -fdefault-integer-8 لجعله يعمل مع أعداد صحيحة 64 بت.على وجه التحديد، مع هذا الرمز:
program inttest
print *, huge(1)
end program inttest
جري
$ gfortran inttest.for
أنشأ ملفًا قابلاً للتنفيذ والذي طبع:
2147483647
ومع ذلك، تشغيل:
$ gfortran -fdefault-integer-8 inttest.for
أدى إلى ملف قابل للتنفيذ والذي أعطى الإخراج:
9223372036854775807
أيضًا، عندما أعلنت عن متغير كعدد صحيح*8 وقمت بتجميعه بدون الخيار -fdefault-integer-8، حصلت على خطأ.الرمز:
program inttest2
integer*8 test_int
test_int = 9223372036854775807
print *, test_int
end program inttest2
جري
$ gfortran inttest2.for
أسفرت
في الملف inttest.for:4
test_int = 9223372036854775807 1
خطأ:عدد صحيح كبير جدًا بالنسبة لنوعه عند (1)
ومع ذلك، سارت الأمور بشكل جيد عندما قمت بالتجميع باستخدام الخيار -fdefault-integer-8 وحصلت على ملف قابل للتنفيذ تمت طباعته
9223372036854775807
ربما تكون هناك خيارات gfortran أخرى قد تكون مفيدة، لكنني لم أقم بالتحقيق فيها أكثر.
من المؤكد أن هذا لا يمنحك 10^14، ولكنه قد يساعد في تفسير النتائج التي رأيتها.