Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

Maximum positive value that can be stored by integer type variable in ABAP is 2147483647.

For values beyond maximum limit of integer variable, workarounds can be used.

One such example is discussion MOD operation fail for large numbers started by m4abrams

I was able to calculate correct result of 512^17 MOD 2773 using the methods detailed below.

I have written this program to do following operations on large integers.

  • Addition
  • Subtraction
  • Multiplication
  • Division
  • Mod
  • Power

Full code snippet is posted at the end of this document.

Program has its flaws, but it works.

I would briefly go through how the logic works.

How are big numbers stored?

Local class lcl_bignum has instance attributes that store big numbers.

LV_STRING - Number stored as string type.

LT_INT - an internal table of integers. The string is broken into substrings of size 4 (base 10000), and those substrings ( as int4 ) are stored in internal table.

LV_SIGN - integer type to store the sign of number. +1 for positive, -1 for negative.

For example, number 1234567890 will be stored in internal table as

LT_INT
7890
3456
12

Why is number broken into base 10000?

Base 10000 is safe considering the capacity of integer variable type in ABAP.

Computing 9999 * 9999 results in 99980001, which is within the limits of integer type.

On the other hand, 99999 * 99999 results in 999980001, which would lead to overflow exception.

How to create instance and store big number?

Below code snippets can be used to create instance of big number.

The constructor parameters are options.


CREATE OBJECT lr3.



--

Above code will create instance with zero value in it.


CREATE OBJECT lr2
  EXPORTING
    i_value = '533335555511111'.



--

Above code will create instance and populate lv_string and lt_int by breaking down input string.

Sign of number is positive by default.

Input string should have only numbers in it.


CREATE OBJECT lr1
  EXPORTING
    i_value = '6584389034291301828999'
    i_negative = 'X'.



--

Using above code, 'X' can be passed i_negative flag if we have a negative number.

How to add numbers?

Instance method Add( ) can be used for adding numbers.

It accepts 2 object reference that need to be added, and result is stored in object whose method gets called.

We are adding the numbers starting lowest weightage (LT_INT[1]), and carrying forward extra in case of overflow.

For example, we add 12345678 and 22223333. Program would add (5678,3333) first, and then (1234,2222).

For A = B + C, below code can be used.


lr3->add( i_obj1 = lr1
          i_obj2 = lr2 ).



--

For A = A + B, below code can be used.


lr3->add( i_obj1 = lr3
          i_obj2 = lr2 ).



--

How to subtract numbers?

Instance method Subtract( ) can be used for subtracting numbers.

The usage is same as Add( ) method.

Looking at code, you would see that Add( ) and Subtract( ) are calling each other.

It is done the tackle how absolute values are treated depending on their sign.

For example, A = B + C, the values of B and C will be added, and common sign will be retained if B and C have same sign. Both positive, or both negative.

If the signs of B and C are different, we essentially have to keep sign of B, and calculate |B| - |C| (absolute values).

How to multiply numbers?

Instance method Multiply( ) can be used.

It accepts 2 object references, and stores result in calling object.

I would explain the logic using example. It is similar to the method used in elementary school.

For elementary example of multiplying 123 and 456, below logic is used.

123

456

===

3*6 + (3*5+2*6) + (3*4+2*5+1*6) + (2*4+1*5) + 1*4

Same thing is done in program at base 10000 level.

At every stage we are carrying forward the overflow value.

How to divide numbers?

For division, I am guessing the answer by multiplying.

Something like binary search, I start with 1 as answer, keep on multiplying it by 10000 still answer crosses dividend.

Once the guess surpasses dividend, I take a step back, and start multiplying by square root of 10000.

A point comes when multiplier is reduced to 1, and multiplication can no longer be used to get closer to answer.

I then use addition to get closer to answer. Instead of square root, divide by 2 to get next "jump value".

A dry run using elementary example would be something like this.

451

4

---

How to do calculate remainder (MOD operation)

Instance method Mod( ) can be used, which internally uses Divide( ), Multiply( ) and Subtract( ).

To calculate A = B MOD C, program does something like:

A = B - C * ( B DIV C )

Here we are reusing the code written in previous methods.

How to calculate Power?

Instance method Power( ) can be used, which internally uses Multiply( ) and Subtract( ).

For calculating A = B POWER C, program starts with 1 as answer, uses loop to multiply B to answer, C number of times.

Full code snippet

  1. *----------------------------------------------------------------------*
  2. *       CLASS lcl_bignum DEFINITION
  3. *----------------------------------------------------------------------*
  4. *
  5. *----------------------------------------------------------------------*
  6. CLASS lcl_bignum DEFINITION.
  7.   PUBLIC SECTION.
  8.     METHODS constructor IMPORTING i_value TYPE string OPTIONAL
  9.                     i_negative  TYPE c OPTIONAL.
  10.     METHODS get_sign RETURNING value(r_sign) TYPE i.
  11.     METHODS get_string RETURNING value(r_string) TYPE string.
  12.     METHODS get_int RETURNING value(r_int) TYPE int4_table.
  13.     METHODS set_data IMPORTING i_value TYPE string
  14.                    i_negative TYPE c OPTIONAL.
  15.     METHODS add IMPORTING i_obj1 TYPE REF TO lcl_bignum
  16.                 i_obj2 TYPE REF TO lcl_bignum.
  17.     METHODS subtract IMPORTING  i_obj1 TYPE REF TO lcl_bignum
  18.                   i_obj2 TYPE REF TO lcl_bignum.
  19.     METHODS multiply IMPORTING  i_obj1 TYPE REF TO lcl_bignum
  20.                   i_obj2 TYPE REF TO lcl_bignum.
  21.     METHODS divide IMPORTING i_obj1 TYPE REF TO lcl_bignum
  22.                  i_obj2 TYPE REF TO lcl_bignum.
  23.     METHODS mod IMPORTING i_obj1 TYPE REF TO lcl_bignum
  24.                 i_obj2 TYPE REF TO lcl_bignum.
  25.     METHODS power IMPORTING i_obj1 TYPE REF TO lcl_bignum
  26.                 i_obj2 TYPE REF TO lcl_bignum.
  27.     METHODS invert_sign.
  28.     METHODS copy_values IMPORTING i_obj TYPE REF TO lcl_bignum.
  29.     METHODS abs_compare IMPORTING i_obj TYPE REF TO lcl_bignum
  30.               RETURNING value(r_result) TYPE i.
  31.   PROTECTED SECTION.
  32.     METHODS int_to_string.
  33.     METHODS split_into_int.
  34.     METHODS delete_leading_zeros.
  35.     METHODS divide_by_2.
  36.   PRIVATE SECTION.
  37.     DATA lv_string TYPE string.
  38.     DATA lv_sign TYPE i VALUE 1.
  39.     DATA lt_int TYPE int4_table.
  40.     "sqrt of max int4 is 46340
  41.     CONSTANTS: gc_unit_size TYPE i VALUE 10000,
  42.            gc_unit_digits TYPE i VALUE 4,
  43.            gc_gt TYPE i VALUE 1"greater than
  44.            gc_lt TYPE i VALUE 2"less than
  45.            gc_eq TYPE i VALUE 0"equals
  46. ENDCLASS.                    "lcl_bignum DEFINITION
  47. *----------------------------------------------------------------------*
  48. *       CLASS lcl_bignum IMPLEMENTATION
  49. *----------------------------------------------------------------------*
  50. *
  51. *----------------------------------------------------------------------*
  52. CLASS lcl_bignum IMPLEMENTATION.
  53.   METHOD constructor.
  54.     IF i_value IS SUPPLIED.
  55.       IF i_value CO ' 1234567890'.
  56.         lv_string = i_value.
  57.         CONDENSE lv_string.
  58.       ENDIF.
  59.       split_into_int( ).
  60.     ENDIF.
  61.     IF i_negative IS SUPPLIED.
  62.       IF i_negative EQ 'X'.
  63.         lv_sign = -1.
  64.       ENDIF.
  65.     ENDIF.
  66.   ENDMETHOD.                    "constructor
  67.   METHOD set_data.
  68.     CLEAR: lv_string, lt_int.
  69.     lv_sign = 1.
  70.     IF i_value CO ' 1234567890'.
  71.       lv_string = i_value.
  72.       CONDENSE lv_string.
  73.     ENDIF.
  74.     split_into_int( ).
  75.     IF i_negative IS SUPPLIED.
  76.       IF i_negative EQ 'X'.
  77.         lv_sign = -1.
  78.       ENDIF.
  79.     ENDIF.
  80.   ENDMETHOD.                    "set_data
  81.   METHOD split_into_int.
  82.     DATA lv_string TYPE string.
  83.     DATA lv_int TYPE i.
  84.     lv_string = me->lv_string.
  85.     WHILE lv_string IS NOT INITIAL.
  86.       IF STRLEN( lv_string ) GT gc_unit_digits.
  87.         SHIFT lv_string RIGHT BY gc_unit_digits PLACES CIRCULAR.
  88.         lv_int = lv_string+0(gc_unit_digits).
  89.         SHIFT lv_string LEFT BY gc_unit_digits PLACES.
  90.       ELSE.
  91.         lv_int = lv_string.
  92.         CLEAR lv_string.
  93.       ENDIF.
  94. *      INSERT lv_int INTO lt_int INDEX 1.
  95.       APPEND lv_int TO lt_int.
  96.     ENDWHILE.
  97.   ENDMETHOD.                    "split_into_int
  98.   METHOD delete_leading_zeros.
  99.     DATA: lt_temp TYPE int4_table,
  100.         lv_temp TYPE i,
  101.         lv_count TYPE i.
  102.     CHECK lt_int IS NOT INITIAL.
  103.     lt_temp = lt_int.
  104.     CLEAR lt_int.
  105.     lv_count = LINES( lt_temp ).
  106.     DO lv_count TIMES.
  107.       READ TABLE lt_temp INTO lv_temp INDEX lv_count.
  108.       IF lv_temp IS NOT INITIAL.
  109.         EXIT.
  110.       ENDIF.
  111.       lv_count = lv_count - 1.
  112.     ENDDO.
  113.     IF lv_count IS NOT INITIAL AND
  114.        lv_count LE LINES( lt_temp ).
  115.       APPEND LINES OF lt_temp FROM 1 TO lv_count TO lt_int.
  116.     ENDIF.
  117.   ENDMETHOD.                    "delete_leading_zeros
  118.   METHOD int_to_string.
  119.     DATA lv_int TYPE i.
  120.     DATA lv_char TYPE n LENGTH gc_unit_digits.
  121.     LOOP AT lt_int INTO lv_int.
  122.       lv_char = lv_int.
  123.       CONCATENATE lv_char lv_string INTO lv_string.
  124.     ENDLOOP.
  125.     SHIFT lv_string LEFT DELETING LEADING '0'.
  126.   ENDMETHOD.                    "int_to_string
  127.   METHOD get_int.
  128.     r_int = lt_int.
  129.   ENDMETHOD.                    "get_int
  130.   METHOD get_sign.
  131.     r_sign = lv_sign.
  132.   ENDMETHOD.                    "get_sign
  133.   METHOD get_string.
  134.     r_string = lv_string.
  135.   ENDMETHOD.                    "get_string
  136.   METHOD copy_values.
  137.     lv_string = i_obj->get_string( ).
  138.     lv_sign = i_obj->get_sign( ).
  139.     lt_int = i_obj->get_int( ).
  140.   ENDMETHOD.                    "copy_values
  141.   METHOD abs_compare.
  142.     DATA: lt_int2 TYPE int4_table,
  143.         lv_int TYPE i,
  144.         lv_int2 TYPE i,
  145.         lv_max TYPE i.
  146.     lt_int2 = i_obj->get_int( ).
  147.     lv_max = LINES( lt_int ).
  148.     IF LINES( lt_int2 ) GT lv_max.
  149.       lv_max = LINES( lt_int2 ).
  150.     ENDIF.
  151.     WHILE lv_max GT 0.
  152.       CLEAR: lv_int,
  153.          lv_int2.
  154.       READ TABLE lt_int INTO lv_int INDEX lv_max.
  155.       READ TABLE lt_int2 INTO lv_int2 INDEX lv_max.
  156.       IF lv_int EQ lv_int2.
  157.         lv_max = lv_max - 1.
  158.       ELSE.
  159.         IF lv_int GT lv_int2.
  160.           r_result = gc_gt.
  161.         ELSEIF lv_int LT lv_int2.
  162.           r_result = gc_lt.
  163.         ENDIF.
  164.         EXIT.
  165.       ENDIF.
  166.     ENDWHILE.
  167.   ENDMETHOD.                    "abs_compare
  168.   METHOD divide_by_2.
  169.     DATA: lv_int TYPE i,
  170.         lt_temp TYPE int4_table,
  171.         lv_mod TYPE i,
  172.         lv_count TYPE i.
  173.     lv_count = LINES( lt_int ).
  174.     DO lv_count TIMES.
  175.       READ TABLE lt_int INTO lv_int INDEX lv_count.
  176.       IF sy-subrc EQ 0.
  177.         lv_int = lv_int + lv_mod * gc_unit_size.
  178.         lv_mod = lv_int MOD 2.
  179.         lv_int = lv_int DIV 2.
  180.         INSERT lv_int INTO lt_temp INDEX 1.
  181.       ENDIF.
  182.       lv_count = lv_count - 1.
  183.     ENDDO.
  184.     lt_int = lt_temp.
  185.     delete_leading_zeros( ).
  186.     int_to_string( ).
  187.   ENDMETHOD.                    "divide_by_2
  188.   METHOD invert_sign.
  189.     lv_sign = lv_sign * -1.
  190.   ENDMETHOD.                    "invert_sign
  191.   METHOD add.
  192.     DATA: lt_int1 TYPE int4_table,
  193.         lt_int2 TYPE int4_table,
  194.         lv_int TYPE i,
  195.         lv_int1 TYPE i,
  196.         lv_int2 TYPE i,
  197.         lv_index TYPE i,
  198.         lv_count TYPE i,
  199.         lv_extra TYPE i.
  200.     lt_int1 = i_obj1->get_int( ).
  201.     lt_int2 = i_obj2->get_int( ).
  202.     IF i_obj1->get_sign( ) NE i_obj2->get_sign( ).
  203.       subtract( i_obj1 = i_obj1
  204.           i_obj2 = i_obj2 ).
  205.       EXIT.
  206.     ENDIF.
  207.     lv_count = LINES( lt_int1 ).
  208.     IF lv_count LT LINES( lt_int2 ).
  209.       lv_count = LINES( lt_int2 ).
  210.     ENDIF.
  211.     CLEAR: lt_int, lv_string.
  212.     lv_sign = i_obj1->get_sign( ).
  213.     DO lv_count TIMES.
  214.       CLEAR: lv_int1,
  215.          lv_int2.
  216.       lv_index = sy-index.
  217.       READ TABLE lt_int1 INTO lv_int1 INDEX lv_index.
  218.       READ TABLE lt_int2 INTO lv_int2 INDEX lv_index.
  219.       lv_int = lv_extra + lv_int1 + lv_int2.
  220.       lv_extra = lv_int DIV gc_unit_size.
  221.       lv_int = lv_int MOD gc_unit_size.
  222.       APPEND lv_int TO lt_int.
  223.     ENDDO.
  224.     int_to_string( ).
  225.   ENDMETHOD.                    "add
  226.   METHOD subtract.
  227.     DATA: lt_int1 TYPE int4_table,
  228.         lt_int2 TYPE int4_table,
  229.         lv_int TYPE i,
  230.         lv_int1 TYPE i,
  231.         lv_int2 TYPE i,
  232.         lv_index TYPE i,
  233.         lv_count TYPE i,
  234.         lv_extra TYPE i.
  235.     FIELD-SYMBOLS: <fs_int> TYPE i.
  236.     lt_int1 = i_obj1->get_int( ).
  237.     lt_int2 = i_obj2->get_int( ).
  238.     IF i_obj1->get_sign( ) NE i_obj2->get_sign( ).
  239.       i_obj2->invert_sign( ).
  240.       add( i_obj1 = i_obj1
  241.          i_obj2 = i_obj2 ).
  242.       EXIT.
  243.     ENDIF.
  244.     lv_count = LINES( lt_int1 ).
  245.     IF lv_count LT LINES( lt_int2 ).
  246.       lv_count = LINES( lt_int2 ).
  247.     ENDIF.
  248.     CLEAR: lt_int, lv_string.
  249.     lv_sign = i_obj1->get_sign( ).
  250.     DO lv_count TIMES.
  251.       CLEAR: lv_int1,
  252.          lv_int2.
  253.       lv_index = sy-index.
  254.       READ TABLE lt_int1 INTO lv_int1 INDEX lv_index.
  255.       READ TABLE lt_int2 INTO lv_int2 INDEX lv_index.
  256.       lv_int = lv_extra + lv_int1 - lv_int2.
  257.       CLEAR lv_extra.
  258.       IF lv_int LT 0.
  259.         lv_int = lv_int + gc_unit_size.
  260.         lv_extra = -1.
  261.       ENDIF.
  262.       lv_int = lv_int MOD gc_unit_size.
  263.       APPEND lv_int TO lt_int.
  264.     ENDDO.
  265.     IF lv_extra IS NOT INITIAL.
  266.       lv_sign = lv_sign * lv_extra.
  267.       LOOP AT lt_int ASSIGNING <fs_int>.
  268.         IF sy-tabix EQ 1.
  269.           <fs_int> = gc_unit_size - <fs_int>.
  270.         ELSE.
  271.           <fs_int> = gc_unit_size - <fs_int> + 1.
  272.         ENDIF.
  273.       ENDLOOP.
  274.     ENDIF.
  275.     delete_leading_zeros( ).
  276.     int_to_string( ).
  277.   ENDMETHOD.                    "subtract
  278.   METHOD multiply.
  279.     DATA: lt_int1 TYPE int4_table,
  280.         lt_int2 TYPE int4_table,
  281.         lv_int TYPE i,
  282.         lv_int1 TYPE i,
  283.         lv_int2 TYPE i,
  284.         lv_int_tmp TYPE i,
  285.         lv_index TYPE i,
  286.         lv_index_start TYPE i,
  287.         lv_index_end   TYPE i,
  288.         lv_index_start_tmp TYPE i,
  289.         lv_index_end_tmp TYPE i,
  290.         lv_count TYPE i,
  291.         lv_carry TYPE i,
  292.         lv_extra TYPE i.
  293.     lt_int1 = i_obj1->get_int( ).
  294.     lt_int2 = i_obj2->get_int( ).
  295.     lv_count = LINES( lt_int1 ).
  296.     IF lv_count LT LINES( lt_int2 ).
  297.       lv_count = LINES( lt_int2 ).
  298.     ENDIF.
  299.     CLEAR: lt_int, lv_string.
  300.     lv_sign = i_obj1->get_sign( ) * i_obj2->get_sign( ).
  301.     CHECK lv_count IS NOT INITIAL.
  302.     lv_index_start = 1.
  303.     lv_index_end   = 1.
  304.     DO.
  305.       CLEAR lv_int.
  306.       lv_index_start_tmp = lv_index_start.
  307.       lv_index_end_tmp   = lv_index_end.
  308.       lv_int = lv_extra.
  309.       CLEAR lv_extra.
  310.       WHILE lv_index_start_tmp LE lv_index_end.
  311.         CLEAR: lv_int1,
  312.              lv_int2.
  313.         READ TABLE lt_int1 INTO lv_int1 INDEX lv_index_start_tmp.
  314.         READ TABLE lt_int2 INTO lv_int2 INDEX lv_index_end_tmp.
  315.         lv_int_tmp = ( lv_int1 * lv_int2 ) MOD gc_unit_size.
  316.         lv_extra = lv_extra + ( lv_int1 * lv_int2 ) DIV gc_unit_size.
  317.         lv_int = lv_int + lv_int_tmp.
  318.         lv_extra = lv_extra + lv_int DIV gc_unit_size.
  319.         lv_int = lv_int MOD gc_unit_size.
  320.         lv_index_start_tmp = lv_index_start_tmp + 1.
  321.         lv_index_end_tmp = lv_index_end_tmp - 1.
  322.       ENDWHILE.
  323.       APPEND lv_int TO lt_int.
  324.       IF lv_index_end LT lv_count.
  325.         lv_index_end = lv_index_end + 1.
  326.       ELSEIF lv_index_start LT lv_count.
  327.         lv_index_start = lv_index_start + 1.
  328.       ELSEIF lv_index_start EQ lv_count AND
  329.        lv_index_end   EQ lv_count.
  330.         EXIT.
  331.       ENDIF.
  332.     ENDDO.
  333.     IF lv_extra IS NOT INITIAL.
  334.       APPEND lv_extra TO lt_int.
  335.     ENDIF.
  336.     delete_leading_zeros( ).
  337.     int_to_string( ).
  338.   ENDMETHOD.                    "multiply
  339.   METHOD divide.
  340.     DATA: lt_int1 TYPE int4_table,
  341.         lt_int2 TYPE int4_table,
  342.         lv_int TYPE i,
  343.         lv_int1 TYPE i,
  344.         lv_int2 TYPE i,
  345.         lv_string1 TYPE string,
  346.         lv_string2 TYPE string,
  347.         lv_index TYPE i,
  348.         lv_count TYPE i,
  349.         lv_extra TYPE i,
  350.         lv_sign1 TYPE i,
  351.         lr1 TYPE REF TO lcl_bignum,
  352.         lr2 TYPE REF TO lcl_bignum,
  353.         lr_guess TYPE REF TO lcl_bignum,
  354.         lr_step TYPE REF TO lcl_bignum,
  355.         lv_step_str TYPE string,
  356.         lv_step TYPE i,
  357.         lr_temp  TYPE REF TO lcl_bignum.
  358.     CREATE OBJECT lr1.
  359.     CREATE OBJECT lr2.
  360.     lr1->copy_values( i_obj1 ).
  361.     lr2->copy_values( i_obj2 ).
  362. *   quotient is zero when divisor is bigger than dividend
  363.     CHECK lr1->abs_compare( lr2 ) EQ gc_gt.
  364.     IF lr1->get_sign( ) LT 0.
  365.       lr1->invert_sign( ).
  366.     ENDIF.
  367.     IF lr2->get_sign( ) LT 0.
  368.       lr2->invert_sign( ).
  369.     ENDIF.
  370. * start with 1, keep multiplying by gc_unit_size
  371.     CREATE OBJECT lr_guess
  372.       EXPORTING
  373.         i_value = '1'.
  374.     CREATE OBJECT lr_temp.
  375.     CREATE OBJECT lr_step.
  376.     lv_step = gc_unit_size.
  377.     DO.
  378.       DO.
  379.         lr_temp->multiply( i_obj1 = lr_guess
  380.                    i_obj2 = lr2 ).
  381.         CASE lr_temp->abs_compare( lr1 ).
  382.           WHEN gc_eq.
  383.             copy_values( lr_guess ).
  384.             RETURN.
  385.           WHEN gc_gt.
  386.             EXIT.
  387.           WHEN gc_lt.
  388. * increment
  389. *            lv_step = gc_unit_size.
  390.             copy_values( lr_guess ).
  391.             lv_step_str = lv_step.
  392.             lr_step->set_data( lv_step_str ).
  393.             lr_guess->multiply( i_obj1 = lr_guess
  394.                       i_obj2 = lr_step ).
  395. *        when others.
  396.        ENDCASE.
  397.       ENDDO.
  398.       lr_guess->copy_values( me ).
  399.       lv_step = SQRT( lv_step ).
  400.       IF lv_step EQ 1.
  401.         EXIT.
  402.       ENDIF.
  403.     ENDDO.
  404. * answer is between guess and guess * 2
  405. * now add steps to move closer to answer
  406. *    lv_step = gc_unit_size.
  407.     lr_step->copy_values( lr_guess ).
  408.     DO.
  409.       DO.
  410.         lr_temp->multiply( i_obj1 = lr_guess
  411.                    i_obj2 = lr2 ).
  412.         CASE lr_temp->abs_compare( lr1 ).
  413.           WHEN gc_eq.
  414.             copy_values( lr_guess ).
  415.             RETURN.
  416.           WHEN gc_gt.
  417.             EXIT.
  418.           WHEN gc_lt.
  419. * increment
  420.             copy_values( lr_guess ).
  421.             lr_guess->add( i_obj1 = lr_guess
  422.                      i_obj2 = lr_step ).
  423. *        when others.
  424.         ENDCASE.
  425.       ENDDO.
  426.       lr_guess->copy_values( me ).
  427. * quick way to divide by 2
  428.       lr_step->divide_by_2( ).
  429.       IF lr_step->get_int( ) IS INITIAL.
  430.         EXIT.
  431.       ENDIF.
  432.     ENDDO.
  433. *    int_to_string( ).
  434.   ENDMETHOD.                    "divide
  435.   METHOD mod.
  436.     DATA lr_div TYPE REF TO lcl_bignum.
  437.     CREATE OBJECT lr_div.
  438.     lr_div->divide( i_obj1 = i_obj1
  439.             i_obj2 = i_obj2 ).
  440.     lr_div->multiply( i_obj1 = lr_div
  441.               i_obj2 = i_obj2 ).
  442.     subtract( i_obj1 = i_obj1
  443.           i_obj2 = lr_div ).
  444.   ENDMETHOD.                    "mod
  445.   METHOD power.
  446.     DATA: lr_power TYPE REF TO lcl_bignum,
  447.         lr_one   TYPE REF TO lcl_bignum.
  448.     CREATE OBJECT lr_one
  449.       EXPORTING
  450.         i_value = '1'.
  451.     CREATE OBJECT lr_power.
  452.     lr_power->copy_values( i_obj2 ).
  453.     lr_power->delete_leading_zeros( ).
  454. * only positive power
  455.     IF get_sign( ) NE lr_power->get_sign( ).
  456.       lr_power->invert_sign( ).
  457.     ENDIF.
  458. * result 1 when power is 0
  459.     set_data( '1' ).
  460.     DO.
  461.       IF lr_power->get_int( ) IS INITIAL.
  462.         EXIT.
  463.       ELSE.
  464.         lr_power->subtract( i_obj1 = lr_power
  465.                   i_obj2 = lr_one ).
  466.         multiply( i_obj1 = me
  467.               i_obj2 = i_obj1 ).
  468.       ENDIF.
  469.     ENDDO.
  470.   ENDMETHOD.                    "power
  471. ENDCLASS.                    "lcl_bignum IMPLEMENTATION
  472. START-OF-SELECTION.
  473.   DATA lr1 TYPE REF TO lcl_bignum.
  474.   DATA lr2 TYPE REF TO lcl_bignum.
  475.   DATA lr3 TYPE REF TO lcl_bignum.
  476.   TRY .
  477.       CREATE OBJECT lr1
  478.         EXPORTING
  479.           i_value = '6584389034291301828999'.
  480. *          i_negative = 'X'.
  481.       CREATE OBJECT lr2
  482.         EXPORTING
  483.           i_value = '533335555511111'.
  484.       CREATE OBJECT lr3.
  485.       lr3->add( i_obj1 = lr1
  486.           i_obj2 = lr2 ).
  487. *     lr3->subtract( i_obj1 = lr1
  488. *                    i_obj2 = lr2 ).
  489. *     lr3->multiply( i_obj1 = lr1
  490. *                    i_obj2 = lr2 ).
  491. *     lr3->divide( i_obj1 = lr1
  492. *                  i_obj2 = lr2 ).
  493. *     lr3->mod( i_obj1 = lr1
  494. *               i_obj2 = lr2 ).
  495.       lr1->set_data( '512' ).
  496.       lr2->set_data( '17' ).
  497.       lr3->power( i_obj1 = lr1
  498.             i_obj2 = lr2 ).
  499.       lr2->set_data( '2773' ).
  500.       lr3->mod( i_obj1 = lr3
  501.           i_obj2 = lr2 ).
  502.     CATCH cx_root.
  503.   ENDTRY.

/.

8 Comments