You could check the length of a string first to see if it has too many digits. But some very large numbers might be stored in scientific notation, which then reduces the length of the string, so checking the string length won't give you an accurate estimate.

I remember, I have written a sub awhile ago that converts a number of any size to scientific notation. This works on extremely large numbers as well and extremely small numbers. It successfully decodes scientific notation, of course, and it treats numbers as a string, so you don't lose any precision. This sub can EASILY be modified to return only the exponent part of a number, not the entire number. Then you should check if the exponent is a positive number, and then how big is it. If it's bigger than, let's say 15, then you know that the number would lose precision if it were treated as a number.

################################################## # v2022.06.30 # Converts a decimal number to scientific notation. # # This function converts a number to standard scientific notation. # This function expects to receive a decimal number, # and it returns a number in scientific notation. # Both the input and output numbers are treated as strings. # If the input string had any spaces, commas or any other illegal # characters, those are removed from the number. # # Example: # # Input: "" Output: "+0E+0" # Input: "-20.35" Output: "-2.035E+1" # Input: "0.000333E-12" Output: "+3.33E-16" # Input: "000.00001000" Output: "+1E-5" # Input: "$ 75,800.99 " Output: "+7.580099E+4" # Input: " (12.49) abc" Output: "-1.249E+1" # Input: " 2008300" Output: "+2.0083E+6" # Input: ".225E+76" Output: "+2.25E+75" # Input: "10,000,000,000,000,000,000,000,000,000,000,000,000,000" # Output: "+1E+40" # # Usage: STRING = SCI(STRING N) # sub SCI { defined $_[0] or return '+0E+0'; my $NUM = $_[0]; my $M = ''; # Mantissa will be stored here my $E = ''; # Exponent will be stored here my $SIGN = 43; # Is this a negative number? (43=pos 45=neg) my $DEC = -1; # Remember the position of the decimal point my $EX = 0; # Exponent (0=no_exp 1=exp_found 43=pos_exp 45=neg_e +xp) my $Z = -1; # Start position of the last zero my $N = -1; # Position of the first non-zero digit for (my $i = 0; $i < length($NUM); $i++) { my $c = vec($NUM, $i, 8); if ($EX) # PROCESS EXPONENT: { if (($c == 43 || $c == 45) && $EX == 1) { $EX = $c; } elsif ($c > 47 && $c < 58) { $E .= chr($c); } elsif (length($E)) { last; } # What comes after the exponent? Nothin +g! } else # PROCESS MANTISSA { if ($c > 47 && $c < 58) # Digits 0-9 { if ($c == 48) { if (length($M)) { $M .= '0'; } # Keep '0' digit only if +there are other digits in front of it if ($Z < 0) { $Z = length($M); } # Remember last insignifi +cant zero } else { $M .= chr($c); # Save digits other than +zero if ($N < 0) { $N = length($M); } $Z = -1; } } elsif ($c == 68 || $c == 69 || $c == 100 || $c == 101) # D/d/E +/e { if (length($M)) { $EX = 1; } # Exponent marker found! } elsif ($c == 46) { if ($DEC < 0) { if (length($M) == 0) { $M = '0'; } $DEC = length($M); # Decimal point found! } else { last; } # A second decimal point? +?? } elsif (($c == 45 || $c == 40) && length($M) == 0) { $SIGN = 45; # It's a negative number } } } if (length($M) == 0) { return '+0E+0'; } # Convert Exponent to a number for now if ($EX) { $EX = ($EX == 45) ? -$E : $E; } # Adjust exponent if (length($M) > 1) { if ($DEC == -1) { $EX = $EX + length($M) - 1; } # No decimal po +int if ($DEC >= 2) { $EX = $EX + $DEC - 1; } # Yes decimal p +oint } # Remove trailing zeros if ($Z > 0) { $M = substr($M, 0, $Z - 1); } # Add decimal point if possible. if ($N > 1) { if (length($M) > $N) { $M = substr($M, $N - 1, 1) . '.' . substr($M, $N); $EX = $EX - $N + 1; } } else { if (length($M) > 1) { $M = substr($M, 0, 1) . '.' . substr($M, 1); + } } return chr($SIGN) . $M . 'E' . ($EX < 0 ? '' : '+') . $EX; } print SCI('00002999999999999900000006.5544433377777777888888880000001' +); exit; # Outputs: # # +2.9999999999999000000065544433377777777888888880000001E+21 #


Merry Christmas!

In reply to Re: Number too big to fit in integer by harangzsolt33
in thread Number too big to fit in integer by jpl

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.