Author Topic: Simulating Addition/Subtraction/Multiplication/Division via strings  (Read 4593 times)

0 Members and 1 Guest are viewing this topic.

Offline Sanmayce

  • Newbie
  • Posts: 63
  • Where is that English Text Sidekick?
    • View Profile
    • Sanmayce's home
Hi,
just saw several fellow members interested in arithmeticity, :P

I wrote this string library back in nineties, it works, as for speed - it was benchmarked successfully on ... 8086, eh. Enjoy!

 
4.PNG


Code: QB64: [Select]
  1. ' RTHMTC.TMR - simulating the four arithmetic operations via strings, written back in 90's by Kaze, (sanmayce[member=743]Sanmayce[/member].com)
  2.  
  3. 'DECLARE SUB DelNull (Result%(), Tiller$, DimLength%)
  4. 'DECLARE SUB DelLeftNull (Result%(), Tiller$, StrLength%, DimLength%, PointPos%)
  5. 'DECLARE SUB DelRightNull (Result%(), Tiller$, StrLength%, PointPos%)
  6. 'DECLARE SUB Convert (Array%(), Number$, Length%, Flag%, PointPos%)
  7. 'DECLARE FUNCTION FindIntegerPart$ (Dividend$, Divisor$)
  8. 'DECLARE FUNCTION DIV$ (Dividend$, Divisor$, Exactness%)
  9. 'DECLARE FUNCTION ADD$ (FirstAddend$, SecondAddend$)
  10. 'DECLARE FUNCTION SUBqb$ (Minuend$, Subtrahend$)
  11. 'DECLARE FUNCTION MUL$ (Multiplicand$, Multiplier$)
  12. 'DECLARE FUNCTION Compare% (Firum$, Secum$)
  13. 'DECLARE FUNCTION ResultFilter$ (Result%(), Code$, DimLength%, PointPos%, Sign%)
  14.  
  15. ' Examples [
  16. PRINT ADD$("123.89", "3")
  17. PRINT SUBqb$("-3", "3")
  18. PRINT MUL$("-0.4", "222222222222222222222222222222222222")
  19. PRINT DIV$("22.7", "-3", 10)
  20. ' Examples ]
  21.  
  22. DEFINT A-Z
  23. FUNCTION ADD$ (FirstAddend$, SecondAddend$)
  24.     FiradLength = LEN(FirstAddend$)
  25.     SecadLength = LEN(SecondAddend$)
  26.     FirstSign$ = MID$(FirstAddend$, 1, 1)
  27.     SecondSign$ = MID$(SecondAddend$, 1, 1)
  28.     IF FirstSign$ <> "-" AND SecondSign$ = "-" THEN
  29.         Mediator$ = RIGHT$(SecondAddend$, SecadLength - 1)
  30.         ADD$ = SUBqb$(FirstAddend$, Mediator$)
  31.         EXIT FUNCTION
  32.     END IF
  33.     IF FirstSign$ = "-" AND SecondSign$ <> "-" THEN
  34.         Mediator$ = RIGHT$(FirstAddend$, FiradLength - 1)
  35.         ADD$ = SUBqb$(SecondAddend$, Mediator$)
  36.         EXIT FUNCTION
  37.     END IF
  38.     IF FirstSign$ = "-" AND SecondSign$ = "-" THEN
  39.         Sign = 1
  40.         FiradLength = FiradLength - 1
  41.         SecadLength = SecadLength - 1
  42.         FirstAddend$ = RIGHT$(FirstAddend$, FiradLength)
  43.         SecondAddend$ = RIGHT$(SecondAddend$, SecadLength)
  44.     END IF
  45.     REDIM Firad%(1 TO FiradLength)
  46.     REDIM Secad%(1 TO SecadLength)
  47.     CALL Convert(Firad%(), FirstAddend$, FiradLength, FiradFlag, FiradPointPos)
  48.     FiradTrueLength = FiradLength - FiradPointPos
  49.     CALL Convert(Secad%(), SecondAddend$, SecadLength, SecadFlag, SecadPointPos)
  50.     SecadTrueLength = SecadLength - SecadPointPos
  51.     IF SecadTrueLength > FiradTrueLength THEN
  52.         BigLength = SecadTrueLength
  53.     ELSE
  54.         BigLength = FiradTrueLength
  55.     END IF
  56.     IF FiradPointPos > SecadPointPos THEN
  57.         BigPointPos = FiradPointPos
  58.         TrueBigPointPos = BigPointPos - FiradFlag
  59.         SubSecad = SecadPointPos - SecadFlag - TrueBigPointPos
  60.     ELSE
  61.         BigPointPos = SecadPointPos
  62.         TrueBigPointPos = BigPointPos - SecadFlag
  63.         SubFirad = FiradPointPos - FiradFlag - TrueBigPointPos
  64.     END IF
  65.     DimSum = BigLength + TrueBigPointPos + 1
  66.     REDIM Result%(1 TO DimSum)
  67.     FOR SF = 1 TO BigLength + BigPointPos
  68.         FiradDim = 0
  69.         SecadDim = 0
  70.         SubFirad = SubFirad + 1
  71.         SubSecad = SubSecad + 1
  72.         IF SubFirad > 0 AND SubFirad <= FiradLength THEN FiradDim = Firad%(SubFirad)
  73.         IF SubSecad > 0 AND SubSecad <= SecadLength THEN SecadDim = Secad%(SubSecad)
  74.         Result%(SF) = FiradDim + SecadDim + Result%(SF)
  75.         IF Result%(SF) >= 10 THEN
  76.             Result%(SF + 1) = 1
  77.             Result%(SF) = Result(SF) - 10
  78.         END IF
  79.     NEXT SF
  80.     ADD$ = ResultFilter$(Result%(), "ADD", DimSum, BigPointPos, Sign)
  81.  
  82. FUNCTION Compare% (Firum$, Secum$)
  83.     FirLeftPart = INSTR(Firum$, ".")
  84.     SecLeftPart = INSTR(Secum$, ".")
  85.     IF FirLeftPart = 0 THEN
  86.         FirLeftPart = LEN(Firum$)
  87.     ELSE
  88.         FirLeftPart = FirLeftPart - 1
  89.         FirRightPart = LEN(Firum$) - FirLeftPart
  90.     END IF
  91.     IF SecLeftPart = 0 THEN
  92.         SecLeftPart = LEN(Secum$)
  93.     ELSE
  94.         SecLeftPart = SecLeftPart - 1
  95.         SecRightPart = LEN(Secum$) - SecLeftPart
  96.     END IF
  97.     IF SecRightPart > FirRightPart THEN
  98.         MainRightPart = FirRightPart
  99.     ELSE
  100.         MainRightPart = SecRightPart
  101.     END IF
  102.     IF SecLeftPart > FirLeftPart THEN
  103.         CompareCode = -1
  104.         MainLeftPart = SecLeftPart
  105.     ELSE
  106.         CompareCode = 1
  107.         MainLeftPart = FirLeftPart
  108.     END IF
  109.     IF SecLeftPart = FirLeftPart THEN
  110.         CompareCode = 0
  111.         DO
  112.             Counter = Counter + 1
  113.             FirumPart = VAL(MID$(Firum$, Counter, 1))
  114.             SecumPart = VAL(MID$(Secum$, Counter, 1))
  115.             IF FirumPart > SecumPart THEN CompareCode = 1
  116.             IF FirumPart < SecumPart THEN CompareCode = -1
  117.         LOOP WHILE Counter < MainLeftPart AND FirumPart = SecumPart
  118.         IF CompareCode = 0 THEN
  119.             MainLength = MainLeftPart + MainRightPart
  120.             IF MainRightPart > 0 THEN
  121.                 Counter = Counter + 1
  122.                 DO
  123.                     Counter = Counter + 1
  124.                     FirumPart = VAL(MID$(Firum$, Counter, 1))
  125.                     SecumPart = VAL(MID$(Secum$, Counter, 1))
  126.                     IF FirumPart > SecumPart THEN CycleFlag = 1: CompareCode = 1
  127.                     IF FirumPart < SecumPart THEN CycleFlag = 1: CompareCode = -1
  128.                 LOOP WHILE Counter < MainLength AND FirumPart = SecumPart
  129.             END IF
  130.             IF Counter = MainLength AND CycleFlag = 0 THEN
  131.                 IF FirRightPart < SecRightPart THEN CompareCode = -1
  132.                 IF FirRightPart > SecRightPart THEN CompareCode = 1
  133.             END IF
  134.         END IF
  135.     END IF
  136.     Compare% = CompareCode
  137.  
  138. SUB Convert (Array%(), Number$, Length, Flag, PointPos)
  139.     FOR Counter = 1 TO Length
  140.         Shoot$ = MID$(Number$, Length - Counter + 1, 1)
  141.         IF Shoot$ = "." THEN
  142.             Flag = 1
  143.             PointPos = Counter
  144.             Counter = Counter + 1
  145.             Shoot$ = MID$(Number$, Length - Counter + 1, 1)
  146.         END IF
  147.         Array%(Counter - Flag) = VAL(Shoot$)
  148.     NEXT Counter
  149.  
  150. SUB DelLeftNull (Result%(), Tiller$, StrLength, DimLength, PointPos)
  151.     Counter = DimLength
  152.     DeviPart = DimLength + 1 - StrLength
  153.     DO WHILE PointPos + 1 <= Counter - DeviPart AND Result%(Counter) = 0
  154.         StrLength = StrLength - 1
  155.         Tiller$ = RIGHT$(Tiller$, StrLength)
  156.         Counter = Counter - 1
  157.     LOOP
  158.  
  159. SUB DelNull (Result%(), Tiller$, DimLength)
  160.     Counter = DimLength
  161.     DO WHILE Result%(Counter) = 0 AND Counter >= 2
  162.         Tiller$ = RIGHT$(Tiller$, Counter - 1)
  163.         Counter = Counter - 1
  164.     LOOP
  165.  
  166. SUB DelRightNull (Result%(), Tiller$, StrLength, PointPos)
  167.     Counter = 1
  168.     NewPointPos = PointPos
  169.     DO WHILE PointPos - 2 >= Counter AND Result%(Counter) = 0
  170.         StrLength = StrLength - 1
  171.         Tiller$ = LEFT$(Tiller$, StrLength)
  172.         Counter = Counter + 1
  173.         NewPointPos = NewPointPos - 1
  174.     LOOP
  175.     PointPos = NewPointPos
  176.  
  177. FUNCTION DIV$ (Dividend$, Divisor$, Exactness)
  178.     DendSign$ = MID$(Dividend$, 1, 1)
  179.     SorSign$ = MID$(Divisor$, 1, 1)
  180.     IF DendSign$ = "-" AND SorSign$ <> "-" THEN
  181.         Sign = 1
  182.         Dividend$ = RIGHT$(Dividend$, LEN(Dividend$) - 1)
  183.     END IF
  184.     IF DendSign$ <> "-" AND SorSign$ = "-" THEN
  185.         Sign = 1
  186.         Divisor$ = RIGHT$(Divisor$, LEN(Divisor$) - 1)
  187.     END IF
  188.     IF DendSign$ = "-" AND SorSign$ = "-" THEN
  189.         Divisor$ = RIGHT$(Divisor$, LEN(Divisor$) - 1)
  190.         Dividend$ = RIGHT$(Dividend$, LEN(Dividend$) - 1)
  191.     END IF
  192.     DendPointPos = INSTR(Dividend$, ".")
  193.     SorPointPos = INSTR(Divisor$, ".")
  194.     IF DendPointPos <> 0 THEN
  195.         DendRightPart = LEN(Dividend$) - DendPointPos
  196.         DendRightPart$ = RIGHT$(Dividend$, DendRightPart)
  197.         Dividend$ = LEFT$(Dividend$, DendPointPos - 1) + DendRightPart$
  198.     END IF
  199.     IF SorPointPos <> 0 THEN
  200.         SorRightPart = LEN(Divisor$) - SorPointPos
  201.         SorRightPart$ = RIGHT$(Divisor$, SorRightPart)
  202.         Divisor$ = LEFT$(Divisor$, SorPointPos - 1) + SorRightPart$
  203.     END IF
  204.     DO WHILE MID$(Dividend$, 1, 1) = "0" AND LEN(Dividend$) <> 1
  205.         Dividend$ = RIGHT$(Dividend$, LEN(Dividend$) - 1)
  206.     LOOP
  207.     DO WHILE MID$(Divisor$, 1, 1) = "0" AND LEN(Divisor$) <> 1
  208.         Divisor$ = RIGHT$(Divisor$, LEN(Divisor$) - 1)
  209.     LOOP
  210.     IF Divisor$ = "0" THEN ERROR 11
  211.     DendLength = LEN(Dividend$)
  212.     SorLength = LEN(Divisor$)
  213.     IF DendLength <= SorLength THEN
  214.         Tiller$ = Dividend$
  215.         Mediator$ = FindIntegerPart$(Dividend$, Divisor$)
  216.         IntegerPart$ = Mediator$
  217.     ELSE
  218.         Pointer = SorLength
  219.         Tiller$ = MID$(Dividend$, 1, Pointer)
  220.         IF FindIntegerPart$(Tiller$, Divisor$) = "0" THEN
  221.             Pointer = SorLength + 1
  222.             Tiller$ = MID$(Dividend$, 1, Pointer)
  223.         END IF
  224.         DO WHILE Pointer < DendLength
  225.             Mediator$ = FindIntegerPart$(Tiller$, Divisor$)
  226.             IntegerPart$ = IntegerPart$ + Mediator$
  227.             Pointer = Pointer + 1
  228.             Shoot$ = MUL$(Mediator$, Divisor$)
  229.             Deviation$ = SUBqb$(Tiller$, Shoot$)
  230.             IF Deviation$ = "0" THEN
  231.                 Tiller$ = MID$(Dividend$, Pointer, 1)
  232.             ELSE
  233.                 Tiller$ = Deviation$ + MID$(Dividend$, Pointer, 1)
  234.             END IF
  235.         LOOP
  236.         Mediator$ = FindIntegerPart$(Tiller$, Divisor$)
  237.         IntegerPart$ = IntegerPart$ + Mediator$
  238.     END IF
  239.     Result$ = IntegerPart$
  240.     RelativePosition = DendRightPart - SorRightPart
  241.     MiddlePosition = LEN(IntegerPart$) - RelativePosition
  242.     CycleLength = Exactness - RelativePosition
  243.     IF CycleLength > 0 THEN
  244.         FOR I = 1 TO CycleLength
  245.             Shoot$ = MUL$(Mediator$, Divisor$)
  246.             Deviation$ = SUBqb$(Tiller$, Shoot$)
  247.             IF Deviation$ = "0" THEN Tiller$ = "0" ELSE Tiller$ = Deviation$ + "0"
  248.             Mediator$ = FindIntegerPart$(Tiller$, Divisor$)
  249.             FractionalPart$ = FractionalPart$ + Mediator$
  250.         NEXT I
  251.         Result$ = Result$ + FractionalPart$
  252.     END IF
  253.     IF MiddlePosition > 0 THEN
  254.         LeftPart$ = LEFT$(Result$, MiddlePosition)
  255.         IF Exactness = 0 THEN
  256.             Result$ = LeftPart$
  257.         ELSE
  258.             RightPart$ = RIGHT$(Result$, LEN(Result$) - MiddlePosition)
  259.             Result$ = LeftPart$ + "." + RightPart$
  260.         END IF
  261.         IF DendLength <= SorLength THEN
  262.             'Below lines for what captain.
  263.             'NullNumber = SorLength - DendLength + 1 'Bug appears here
  264.             '                                        'because +1 or +0 must.
  265.             'IF MiddlePosition > NullNumber THEN
  266.             'DelLength = NullNumber
  267.             'ELSEIF MiddlePosition = NullNumber THEN
  268.             'DelLength = NullNumber - 1
  269.             'ELSEIF MiddlePosition > 1 THEN
  270.             'DelLength = MiddlePosition - 1
  271.             'END IF
  272.             'Result$ = RIGHT$(Result$, LEN(Result$) - DelLength)
  273.             DO WHILE LEN(Result$) >= 2
  274.                 IF LEFT$(Result$, 1) = "0" AND MID$(Result$, 2, 1) <> "." THEN
  275.                     Result$ = RIGHT$(Result$, LEN(Result$) - 1)
  276.                 ELSE
  277.                     EXIT DO
  278.                 END IF
  279.             LOOP
  280.         END IF
  281.     ELSE
  282.         IF MiddlePosition = 0 THEN
  283.             Result$ = "0." + Result$
  284.         ELSE
  285.             Result$ = "0." + STRING$(ABS(MiddlePosition), "0") + Result$
  286.         END IF
  287.         IF Exactness = 0 THEN
  288.             Result$ = "0"
  289.         ELSEIF CycleLength < 0 THEN
  290.             Result$ = LEFT$(Result$, 2 + Exactness)
  291.         END IF
  292.     END IF
  293.     IF Sign = 1 THEN DIV$ = "-" + Result$ ELSE DIV$ = Result$
  294.  
  295. FUNCTION FindIntegerPart$ (Dividend$, Divisor$)
  296.     DO
  297.         Counter = Counter + 1
  298.         Digit$ = LTRIM$(STR$(Counter))
  299.         Tiller$ = MUL$(Digit$, Divisor$)
  300.         CompareCode = Compare%(Tiller$, Dividend$)
  301.     LOOP WHILE Counter <= 9 AND CompareCode = -1
  302.     FindIntegerPart$ = LTRIM$(STR$(Counter - CompareCode))
  303.  
  304. FUNCTION MUL$ (Multiplicand$, Multiplier$)
  305.     CandSign$ = MID$(Multiplicand$, 1, 1)
  306.     ErSign$ = MID$(Multiplier$, 1, 1)
  307.     CandLength = LEN(Multiplicand$)
  308.     ErLength = LEN(Multiplier$)
  309.     IF CandSign$ = "-" AND ErSign$ <> "-" THEN
  310.         Sign = 1
  311.         CandLength = CandLength - 1
  312.         Multiplicand$ = RIGHT$(Multiplicand$, CandLength)
  313.     END IF
  314.     IF CandSign$ <> "-" AND ErSign$ = "-" THEN
  315.         Sign = 1
  316.         ErLength = ErLength - 1
  317.         Multiplier$ = RIGHT$(Multiplier$, ErLength)
  318.     END IF
  319.     IF CandSign$ = "-" AND ErSign$ = "-" THEN
  320.         ErLength = ErLength - 1
  321.         CandLength = CandLength - 1
  322.         Multiplier$ = RIGHT$(Multiplier$, ErLength)
  323.         Multiplicand$ = RIGHT$(Multiplicand$, CandLength)
  324.     END IF
  325.     REDIM Cand%(1 TO CandLength)
  326.     REDIM Er%(1 TO ErLength)
  327.     CALL Convert(Cand%(), Multiplicand$, CandLength, CandFlag, CandPointPos)
  328.     CALL Convert(Er%(), Multiplier$, ErLength, ErFlag, ErPointPos)
  329.     DimSum = CandLength + ErLength - CandFlag - ErFlag
  330.     PointPos = CandPointPos + ErPointPos - CandFlag - ErFlag
  331.     REDIM Result%(1 TO DimSum)
  332.     FOR SF = 1 TO CandLength - CandFlag
  333.         FOR QB = 1 TO ErLength - ErFlag
  334.             CarryFlag = 0
  335.             Cycle = QB - 1 + SF
  336.             Tiller = Cand%(SF) * Er%(QB)
  337.             Result%(Cycle) = Tiller MOD 10 + Result%(Cycle)
  338.             IF Result%(Cycle) >= 10 THEN
  339.                 Result%(Cycle) = Result%(Cycle) - 10
  340.                 CarryFlag = 1
  341.             END IF
  342.             NextNumPos = Cycle + 1
  343.             Result%(NextNumPos) = Result%(NextNumPos) + CarryFlag + Tiller \ 10
  344.             DO WHILE Result%(NextNumPos) >= 10
  345.                 Result%(NextNumPos) = Result%(NextNumPos) - 10
  346.                 NextNumPos = NextNumPos + 1
  347.                 Result%(NextNumPos) = Result%(NextNumPos) + 1
  348.             LOOP
  349.         NEXT QB
  350.     NEXT SF
  351.     MUL$ = ResultFilter$(Result%(), "MUL", DimSum, PointPos, Sign)
  352.  
  353. FUNCTION ResultFilter$ (Result%(), Code$, DimLength, PointPos, Sign)
  354.     SELECT CASE Code$
  355.         CASE "ADD"
  356.             FOR I = 1 TO DimLength - 1
  357.                 IF I = PointPos THEN Tiller$ = "." + Tiller$
  358.                 Tiller$ = LTRIM$(STR$(Result%(I))) + Tiller$
  359.             NEXT I
  360.             IF Result%(DimLength) <> 0 THEN
  361.                 Tiller$ = LTRIM$(STR$(Result%(DimLength))) + Tiller$
  362.             END IF
  363.             IF PointPos <> 0 THEN
  364.                 StrLength = LEN(Tiller$)
  365.                 CALL DelRightNull(Result%(), Tiller$, StrLength, PointPos)
  366.             END IF
  367.             IF Sign = 1 THEN Tiller$ = "-" + Tiller$
  368.         CASE "SUB"
  369.             FOR I = 1 TO DimLength
  370.                 IF I = PointPos THEN Tiller$ = "." + Tiller$
  371.                 Tiller$ = LTRIM$(STR$(Result%(I))) + Tiller$
  372.             NEXT I
  373.             IF PointPos <> 0 THEN
  374.                 StrLength = LEN(Tiller$)
  375.                 CALL DelRightNull(Result%(), Tiller$, StrLength, PointPos)
  376.                 CALL DelLeftNull(Result%(), Tiller$, StrLength, DimLength, PointPos)
  377.             ELSE
  378.                 CALL DelNull(Result%(), Tiller$, DimLength)
  379.             END IF
  380.             IF Sign = -1 THEN Tiller$ = "-" + Tiller$
  381.         CASE "MUL"
  382.             FOR I = 1 TO DimLength
  383.                 Tiller$ = LTRIM$(STR$(Result%(I))) + Tiller$
  384.                 IF I = PointPos THEN Tiller$ = "." + Tiller$
  385.             NEXT I
  386.             IF Result%(DimLength) = 0 THEN
  387.                 IF PointPos = 0 THEN
  388.                     Tiller$ = RIGHT$(Tiller$, DimLength - 1)
  389.                     IF MID$(Tiller$, 1, 1) = "0" THEN Tiller$ = "0"
  390.                 ELSE
  391.                     PointPos = PointPos + 1
  392.                     Tiller$ = RIGHT$(Tiller$, DimLength)
  393.                     StrLength = LEN(Tiller$)
  394.                     TrueDimLength = StrLength - 1
  395.                     CALL DelRightNull(Result%(), Tiller$, StrLength, PointPos)
  396.                     CALL DelLeftNull(Result%(), Tiller$, StrLength, TrueDimLength, PointPos)
  397.                 END IF
  398.             END IF
  399.             IF Sign = 1 THEN Tiller$ = "-" + Tiller$
  400.     END SELECT
  401.     IF RIGHT$(Tiller$, 2) = ".0" THEN Tiller$ = LEFT$(Tiller$, LEN(Tiller$) - 2)
  402.     IF Tiller$ = "-0" THEN Tiller$ = "0"
  403.     ResultFilter$ = Tiller$
  404.  
  405. FUNCTION SUBqb$ (Minuend$, Subtrahend$)
  406.     MinuSign$ = MID$(Minuend$, 1, 1)
  407.     SubtraSign$ = MID$(Subtrahend$, 1, 1)
  408.     MinuLength = LEN(Minuend$)
  409.     SubtraLength = LEN(Subtrahend$)
  410.     IF MinuSign$ = "-" AND SubtraSign$ <> "-" THEN
  411.         Mediator$ = RIGHT$(Minuend$, MinuLength - 1)
  412.         SUBqb$ = "-" + ADD$(Mediator$, Subtrahend$)
  413.         EXIT FUNCTION
  414.     END IF
  415.     IF MinuSign$ <> "-" AND SubtraSign$ = "-" THEN
  416.         Mediator$ = RIGHT$(Subtrahend$, SubtraLength - 1)
  417.         SUBqb$ = ADD$(Minuend$, Mediator$)
  418.         EXIT FUNCTION
  419.     END IF
  420.     IF MinuSign$ = "-" AND SubtraSign$ = "-" THEN
  421.         SWAP Minuend$, Subtrahend$
  422.         MinuLength = MinuLength - 1
  423.         SubtraLength = SubtraLength - 1
  424.         Minuend$ = RIGHT$(Minuend$, MinuLength)
  425.         Subtrahend$ = RIGHT$(Subtrahend$, SubtraLength)
  426.     END IF
  427.     REDIM Minu%(1 TO MinuLength)
  428.     REDIM Subtra%(1 TO SubtraLength)
  429.     CALL Convert(Minu%(), Minuend$, MinuLength, MinuFlag, MinuPointPos)
  430.     MinuTrueLength = MinuLength - MinuPointPos
  431.     CALL Convert(Subtra%(), Subtrahend$, SubtraLength, SubtraFlag, SubtraPointPos)
  432.     SubtraTrueLength = SubtraLength - SubtraPointPos
  433.     IF SubtraTrueLength > MinuTrueLength THEN
  434.         MainTrueLength = SubtraTrueLength
  435.     ELSE
  436.         MainTrueLength = MinuTrueLength
  437.     END IF
  438.     CompareCode = Compare%(Minuend$, Subtrahend$)
  439.     IF CompareCode = -1 THEN Sign = -1 ELSE Sign = 1
  440.     IF MinuPointPos < SubtraPointPos THEN
  441.         BigPointPos = SubtraPointPos
  442.         TrueBigPointPos = BigPointPos - SubtraFlag
  443.         MinuSub = MinuPointPos - MinuFlag - TrueBigPointPos
  444.     ELSE
  445.         BigPointPos = MinuPointPos
  446.         TrueBigPointPos = BigPointPos - MinuFlag
  447.         SubtraSub = SubtraPointPos - SubtraFlag - TrueBigPointPos
  448.     END IF
  449.     DimSum = MainTrueLength + TrueBigPointPos
  450.     REDIM Result%(1 TO DimSum)
  451.     FOR SF = 1 TO DimSum
  452.         MinuDim = 0
  453.         SubtraDim = 0
  454.         MinuSub = MinuSub + 1
  455.         SubtraSub = SubtraSub + 1
  456.         IF MinuSub > 0 AND MinuSub <= MinuLength - MinuFlag THEN
  457.             MinuDim = Minu%(MinuSub)
  458.         END IF
  459.         IF SubtraSub > 0 AND SubtraSub <= SubtraLength - SubtraFlag THEN
  460.             SubtraDim = Subtra%(SubtraSub)
  461.         END IF
  462.         IF Sign = 1 THEN
  463.             MinuDim = MinuDim + SubFlag
  464.         ELSE
  465.             SubtraDim = SubtraDim + SubFlag
  466.         END IF
  467.         SubSum = Sign * (MinuDim - SubtraDim)
  468.         SubFlag = 0
  469.         IF Sign = 1 THEN
  470.             IF MinuDim >= SubtraDim THEN
  471.                 Result%(SF) = SubSum
  472.             ELSE
  473.                 IF SubSum < 0 THEN SubFlag = -1
  474.                 Result%(SF) = SubSum + 10
  475.             END IF
  476.         ELSE
  477.             IF MinuDim > SubtraDim THEN
  478.                 IF SubSum < 0 THEN SubFlag = -1
  479.                 Result%(SF) = SubSum + 10
  480.             ELSE
  481.                 Result%(SF) = SubSum
  482.             END IF
  483.         END IF
  484.     NEXT SF
  485.     SUBqb$ = ResultFilter$(Result%(), "SUB", DimSum, BigPointPos, Sign)
  486.  

@luke  @Pete  @bplus  @George McGinn

Add-on:
Having seen @bplus' results wanted to benchmark my arithmetic library with Fibonacci - the speed is awful, 20x slower, :(

https://www.qb64.org/forum/index.php?topic=2921.msg133317#msg133317

 
10000.png


Also, here comes the 10000! benchmark, have to change the INT to LNG (i.e. all % to &) in order to work with 32+K strings:

 
fact.png

* Fibonacci_Kaze.bas (Filesize: 19.35 KB, Downloads: 155)
* factorial_Kaze.bas (Filesize: 19.3 KB, Downloads: 178)
« Last Edit: June 19, 2021, 04:25:09 am by Sanmayce »
He learns not to learn and reverts to what all men pass by.

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: Simulating Addition/Subtraction/Multiplication/Division via strings
« Reply #1 on: June 19, 2021, 11:45:28 am »
hello Sanmayce
interesting, I bet you could speed-up your code a lot if instead of doing one digit at a time you do 8 or 9 digits at a time
for addition and subtraction you could possibly use _Integer64 for the elements and process 18 digits at a time
a 9 digit product will fit in an _Integer64, so you could use longs for multiplication
also you could transfer your numeric string to an array of longs or _Integer64, that would simplify accessing the elements, then after the operation was finished transfer the array back to string

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Simulating Addition/Subtraction/Multiplication/Division via strings
« Reply #2 on: June 19, 2021, 12:32:34 pm »
I see a problem with the division -

When I put this statement in: PRINT DIV$("22", "7", 150) to calculate the value of PI out to 150 decimal places, it repeats a pattern after 7 decimals (see below).

 
Screenshot from 2021-06-19 12-31-57.png
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: Simulating Addition/Subtraction/Multiplication/Division via strings
« Reply #3 on: June 19, 2021, 12:55:08 pm »
George, there's no error, the output is correct

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: Simulating Addition/Subtraction/Multiplication/Division via strings
« Reply #4 on: June 19, 2021, 02:06:49 pm »
speaking of Pi
Code: QB64: [Select]
  1.  
  2. digits = 100
  3. beginT# = Timer
  4. a$ = arc_tan$(57, digits)
  5. pi$ = MUL$(a$, "44")
  6. a$ = arc_tan$(239, digits)
  7. a$ = MUL$(a$, "7")
  8. pi$ = ADD$(pi$, a$)
  9. a$ = arc_tan$(682, digits)
  10. a$ = MUL$(a$, "12")
  11. pi$ = SUBqb$(pi$, a$)
  12. a$ = arc_tan$(12943, digits)
  13. a$ = MUL$(a$, "24")
  14. pi$ = ADD$(pi$, a$)
  15. pi$ = MUL$(pi$, "4")
  16. pi$ = Left$(pi$, digits + 2)
  17. Print "Pi = "; pi$
  18.  
  19. Print "Done in"; Timer - beginT#; "seconds."
  20.  
  21. DefLng A-Z
  22. Function arc_tan$ (d As Long, digits As Long)
  23.     Dim As Long i
  24.     Dim As String arr1, arr2, arr_help
  25.     i = 1
  26.     arr_help = "1"
  27.  
  28.     arr_help = DIV$(arr_help, LTrim$(Str$(d)), digits + 4)
  29.     arr1 = ADD$(arr1, arr_help)
  30.  
  31.     Do
  32.         arr_help = DIV$(arr_help, LTrim$(Str$(d)), digits + 4)
  33.         arr_help = DIV$(arr_help, LTrim$(Str$(d)), digits + 4)
  34.         i = i + 2
  35.         ' copy arr_help into arr2
  36.         arr2 = arr_help
  37.         arr2 = DIV$(arr2, LTrim$(Str$(i)), digits + 4)
  38.         arr1 = SUBqb$(arr1, arr2)
  39.         arr_help = DIV$(arr_help, LTrim$(Str$(d)), digits + 4)
  40.         arr_help = DIV$(arr_help, LTrim$(Str$(d)), digits + 4)
  41.         i = i + 2
  42.         ' copy arr_help into arr2
  43.         arr2 = arr_help
  44.         arr2 = DIV$(arr2, LTrim$(Str$(i)), digits + 4)
  45.         arr1 = ADD$(arr1, arr2)
  46.         If Compare&(arr2, "0." + String$(digits + 3, "0") + "1") >= 0 Then GoTo Continue
  47.         ' we get here only if arr2 is filled with zero's ("0")
  48.         Exit Do
  49.         Continue:
  50.     Loop
  51.     arc_tan = arr1
  52.  

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Simulating Addition/Subtraction/Multiplication/Division via strings
« Reply #5 on: June 19, 2021, 02:49:29 pm »
@jack - You are right.

I tried this for more precision (77/2 just approximates PI): PRINT DIV$("245850922", "78256779", 150)

That got me much further into the number - about 50 to 80 decimal places before I had repeaters.
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline Sanmayce

  • Newbie
  • Posts: 63
  • Where is that English Text Sidekick?
    • View Profile
    • Sanmayce's home
Re: Simulating Addition/Subtraction/Multiplication/Division via strings
« Reply #6 on: June 20, 2021, 03:39:39 am »
Hi jack,
thanks for the suggestions, I am always open to new ideas, but these months I have no time even for my kinda frozen Textual-Madness project. The shared school-method basic arithmetic functions were written in QuickBasic 2.0 as an expression of ... stringomania.

Regarding, digit-to-digit optimization, I rewrote the multiplication in C using lookup tables and ... the Karatsuba scheme - 16 threaded, you know, just for fun purposes and benchmarking.

@david_uwi

The attached MokujIN package has the EXE/ELF and the C source which computes (as command prompt parameters) 524288^^524288 = (2^^19)^^(2^^19) = 2^^(19*524288) = 2^^(9961472) ...

This is the laddy called Anatoly Karatsuba, the nightmare for Akad. Kolmogorov:

 
karatsuba.png


This PDF is very instrumental, for all wanting to get the down-the-years picture:
https://www.math.ntnu.no/seminarer/perler/2019-09-06.pdf

My adash (an orientalism, meaning 'namesake') and you jack, might find this interesting (the unseen slowness of Intel CPUs, shown by my humble persona, was one of the reasons to get me banned from IDZ - Intel Developer Zone forum, as if it was my fault, an ugly behavior indeed):
https://www.overclock.net/threads/cpu-benchmark-spigot-pi.1752820/#post-28567752

Thinking from another perspective, I got awarded with 'BAN', for several years of sharing my C code.

Anyway, wrote another short CONSOLE tool dumping Fibonacci numbers in a file, it finds 1000th number in 239 seconds on i5-7200U:

 
111.png


And loading this 275KB file (attached below) into Masakari_Vanilla_NEC (with 300x80 matrix):

 
2021-06-20_095730.png
* Fibonacci_dumper.bas (Filesize: 23.99 KB, Downloads: 162)
* groups_of_280-digits.txt (Filesize: 275.39 KB, Downloads: 197)
* MokujIN_r5++_(ELF+EXE)_vs_GMP.zip (Filesize: 11.13 MB, Downloads: 148)
« Last Edit: June 20, 2021, 04:41:41 am by Sanmayce »
He learns not to learn and reverts to what all men pass by.

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: Simulating Addition/Subtraction/Multiplication/Division via strings
« Reply #7 on: June 20, 2021, 06:09:42 am »
Hi Sanmayce
very interesting reads and code, thank you

Offline euklides

  • Forum Regular
  • Posts: 128
    • View Profile
Re: Simulating Addition/Subtraction/Multiplication/Division via strings
« Reply #8 on: June 23, 2021, 05:24:14 am »
This program would be very useful for calculating spatial trajectories (+ a bit of trigonometry).
Interesting.
Also for the search of prime numbers ...
Why not yes ?