f77coder has asked for the wisdom of the Perl Monks concerning the following question:

i saw this code on a test site and am curious how would Perl implement arithmatic exceptions?

this code will probably bomb if the 1 input array is MIN/MAX_INT or 2 the array is too large, O(n2)

I've been looking around at arbitrary precision libs but looking for a native Perl solution without external libs

bad code

int foo ( int A[], int n ) { int k, m, lsum, rsum; for(k = 0; k < n; ++k) { lsum = 0; rsum = 0; for(m = 0; m < k; ++m) lsum += A[m]; for(m = k + 1; m < n; ++m) rsum += A[m]; if (lsum == rsum) return k; } return -1; }

fixed code

int foo(int arr[], int n) { if (n==0) return -1; long long sum = 0; int i; for(i=0;i<n;i++) sum+=(long long) arr[i]; long long sum_left = 0; for(i=0;i<n;i++) { long long sum_right = sum - sum_left - (long long) arr[i]; if (sum_left == sum_right) return i; sum_left += (long long) arr[i]; } return -1; }

Replies are listed 'Best First'.
Re: How does Perl handle arithmetic overflows?
by dave_the_m (Monsignor) on Sep 08, 2016 at 10:56 UTC
    Internally, perl changes the data type of variables where necessary/possible in arithmetic to try to avoid loss of precision and/or overflow. So for example on a typical 64-bit system, repeated $x += 1 will cause the internal type to change from being initially a signed 64-bit int, to an unsigned 64-bit, and finally to a double - at which point it doesn't overflow, but may lose precision.

    The exact details of what types are used at what points depends on the platform.

    Dave.

      Great, thank you.

Re: How does Perl handle arithmetic overflows?
by Corion (Patriarch) on Sep 08, 2016 at 10:56 UTC

    If you really need arbitrary precision beyond what your Perl has been compiled to use as floating point values, have a look at Math::BigInt and/or Math::BigRat (and bignum. Perl will automatically switch from integer calculations to floating point calculations if the numbers involved in an operation get too large, so your problem will not be with underflow/overflow but with precision.

    I think that by carefully looking at the actual numerical conversions, you can also get by with simply using the Perl native operations, but as I mostly work in the integer domain, I haven't had to do so myself.

    Personally, I'm not too sure if I understood your C code correctly and understood where you feel there are problems. From my cursory reading, I understand that your code iterates over the first n elements of array A (or arr in the second example) and tries to find an index where the sum of the values in the array left of that index is identical to the sum on the right of that index.

    Your use of long long types suggests to me that you are afraid of the sum getting too large and getting integer addition overflows, but I'm not sure if you're also afraid of n overflowing and not being able to reach all array elements or if that is actually an issue in C.

      Many thanks for your answer.

      how would Perl handle precision if left sum approaches INT_MAX while the right sum ~0?

      of if the unknown array is actually LLONG_MAX?