كيف يمكنني تعطيل العلمي عند العمل مع أعداد كبيرة جدا في بيرل؟

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

سؤال

والنظر في المسائل التالية:

print 3 ** 333; #Yields 7.6098802313206e+158

وسؤالي بسيط: كيف يمكنني تعطيل العلمي عند العمل مع أعداد كبيرة جدا؟ في الأساس، وأنا أود أن أرى كل الأرقام ملقاة على stdout حرفيا.

هل هذا ممكن؟

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

المحلول

وانظر Math::BigInt

use Math::BigInt;
$x = Math::BigInt->new("3");
print $x ** 333;

وإخراج:

760988023132059809720425867265032780727896356372077865117010037035791631439306199613044145649378522557935351570949952010001833769302566531786879537190794573523

نصائح أخرى

إذا كنت تريد أن تفعل ذلك لجميع الأعداد الصحيحة في البرنامج، يمكنك إضافة فقط:

use bigint;

إذا كنت تريد فقط أن نفعل ذلك لبعض الأعداد الصحيحة، يمكنك إنشاء الرياضيات :: BIGINT التحف.

وهناك أيضا bignum و <لأ href = "HTTP: //search.cpan. غزاله / حي / الرياضيات BigNum "يختلط =" noreferrer "> الرياضيات :: BigNum إذا كنت تعمل مع عوامات.

لقيم صغيرة جدا راجع التعليمات البرمجية التالية:

my $value = 1e-07;                 # = 0.0000001

# NOPE

print $value;                      # prints 1e-07, $value is a number
print sprintf("%f", $value);       # prints 0, $value is a number
print sprintf("%.10f", $value);    # prints 0.0000001000, $value is a number
$value = sprintf("%.10f", $value);
print $value                       # prints 1e-07, $value is a number

# /NOPE

use bignum;
$value = ($value+0)->bstr();
print $value;                      # prints 0.0000001, $value is a string
no bignum;
print $value;                      # prints 0.0000001, $value is a string

# HOORAY

ومع الأرقام التي كبير قد يكون لديك أرقام أكثر من الدقة تستخدم لتخزين الأرقام. (رؤية مثال بسيط runnable قد حل هذه المسألة).

إذا كنت حقا بحاجة الى ان نرى جميع الأرقام 150+، يجب عليك استخدام BIGINT (للالأعداد الصحيحة)، bigrat (للأرقام عقلانية) وbignum (للأرقام النقطة العائمة) وحدات.

وكان نفس العدد مع هذا الرمز:

#!/usr/bin/perl
use strict;
use warnings;
print "Base Exp    MAX Signed-Negitive     MAX Signed-Positive            MAX Unsigned\n";
for( my $x = 1; $x <= 64; $x++ ) {
    my $y = (2 ** $x);
    printf( "2 ^ %4d = %20d to %-20d or %20d\n",
                 $x,   $y/-2,  $y/2,    $y );
}

وخطوط الماضيين حيث الطباعة:

2 ^   63 = -4611686018427387904 to 4611686018427387904  or -9223372036854775808
2 ^   64 = -9223372036854775808 to -9223372036854775808 or                   -1

ومن الواضح أن ليس صحيحا، وليس تحقيق٪ د التحويل والتي تسبب المشكلة، حاولت حل ترفع علم هنا:

#!/usr/bin/perl
use strict;
use warnings;
use Math::BigInt;
print "Base Exp    MAX Signed-Negitive     MAX Signed-Positive            MAX Unsigned\n";
for( my $x = Math::BigInt->new('1'); $x <= 64; $x++ ) {
    my $y = Math::BigInt->new(2 ** $x);
    printf( "2 ^ %4d = %20d to %-20d or %20d\n",
                 $x,   $y/-2,  $y/2,    $y );
}

وذلك عندما أدركت printf 'د' تحويل كان يسبب مشكلة. القراءة على الرياضيات :: BIGINT يبدو تشير إلى أن يتم تخزين هذه الأرقام كسلاسل الداخل، لذلك تغيير لتحويل الصورة، إصلاح المشكلة:

#!/usr/bin/perl
use strict;
use warnings;
use Math::BigInt;
print "Base Exp    MAX Signed-Negitive     MAX Signed-Positive            MAX Unsigned\n";
for( my $x = Math::BigInt->new('1'); $x <= 64; $x++ ) {
    my $y = Math::BigInt->new(2 ** $x);
    printf( "2 ^ %4s = %20s to %-20s or %20s\n",
                 $x,   $y/-2,  $y/2,    $y );
}

والآن السطرين الأخيرين المطبوعة بشكل صحيح:

2 ^   63 = -4611686018427387904 to 4611686018427387904  or  9223372036854775808
2 ^   64 = -9223372036854775808 to 9223372036854775808  or 18446744073709551616

ولكن في ما يخص الإجابة كاريل، الذي كان IMHO الصحيح تقريبا، وهذا يمكن أيضا أن يتم ذلك دون استخدام BIGINT (BIGINT، BigNum، ...) عن طريق استخدام 'و' تحويل ولكن مع الدقة لمجموعة '0 "للقضاء على تلك الكسور العشرية:

#!/usr/bin/perl
use strict;
use warnings;
print "Base Exp    MAX Signed-Negitive     MAX Signed-Positive            MAX Unsigned\n";
for( my $x = 1; $x <= 64; $x++ ) {
    my $y = (2 ** $x);
    printf( "2 ^ %4d = %20.0f to %-20.0f or %20.0f\n",
                 $x,   $y/-2,  $y/2,    $y );
}

وهذا يعمل أيضا للسؤال OP و:

perl -e 'printf "%.0f\n", 3 ** 333'
760988023132059813486251563646478824265752535077884574263917414498578085812167738721447369281049109603746001743233145041176969930222526036520619613114171654144
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top