Procedure.s DetermineSign(a.s, b.s, operation.s)
Protected signA = 1
Protected signB = 1
; Определяем знаки чисел
If Left(a, 1) = "-"
signA = -1
a = Right(a, Len(a) - 1)
EndIf
If Left(b, 1) = "-"
signB = -1
b = Right(b, Len(b) - 1)
EndIf
; Определяем знак результата в зависимости от операции
Select operation
Case "+"
If signA = signB
ProcedureReturn Str(signA)
Else
If signA = 1
ProcedureReturn "subtract"
Else
ProcedureReturn "subtract_reverse"
EndIf
EndIf
Case "-"
If signA = signB
If signA = 1
ProcedureReturn "subtract"
Else
ProcedureReturn "subtract_reverse"
EndIf
Else
ProcedureReturn Str(signA)
EndIf
Case "*"
ProcedureReturn Str(signA * signB)
Case "/"
ProcedureReturn Str(signA * signB)
EndSelect
EndProcedure
Procedure.s String(char.s, count)
Protected result.s = ""
For i = 1 To count
result + char
Next
ProcedureReturn result
EndProcedure
Declare.s AddLongNumbers(a.s,b.s)
Procedure.s SubtractLongNumbers(a.s, b.s)
Protected signResult.s = DetermineSign(a, b, "-")
; Убираем знаки из чисел
If Left(a, 1) = "-"
a = Right(a, Len(a) - 1)
EndIf
If Left(b, 1) = "-"
b = Right(b, Len(b) - 1)
EndIf
; Если знак результата требует сложения
If signResult = "1" Or signResult = "-1"
ProcedureReturn AddLongNumbers(a, b)
EndIf
; Выполняем вычитание
Protected borrow = 0
Protected result.s = ""
Protected i, diff, digitA, digitB
; Выравниваем числа по десятичной точке
Protected aPoint = FindString(a, ".", 1)
Protected bPoint = FindString(b, ".", 1)
If aPoint = 0
a + ".0"
aPoint = Len(a) - 1
EndIf
If bPoint = 0
b + ".0"
bPoint = Len(b) - 1
EndIf
; Выравниваем дробные части
While Len(a) - aPoint < Len(b) - bPoint
a + "0"
Wend
While Len(b) - bPoint < Len(a) - aPoint
b + "0"
Wend
; Выравниваем целые части
While aPoint < bPoint
a = "0" + a
aPoint + 1
Wend
While bPoint < aPoint
b = "0" + b
bPoint + 1
Wend
; Вычитаем цифры справа налево
For i = Len(a) To 1 Step -1
If Mid(a, i, 1) = "."
result = "." + result
Continue
EndIf
digitA = Val(Mid(a, i, 1)) - borrow
digitB = Val(Mid(b, i, 1))
If digitA < digitB
digitA + 10
borrow = 1
Else
borrow = 0
EndIf
diff = digitA - digitB
result = Str(diff) + result
Next
; Убираем ведущие нули
While Left(result, 1) = "0" And Len(result) > 1 And Mid(result, 2, 1) <> "."
result = Right(result, Len(result) - 1)
Wend
; Добавляем знак результата
If signResult = "-1"
result = "-" + result
EndIf
ProcedureReturn result
EndProcedure
Procedure.s AddLongNumbers(a.s, b.s)
Protected signResult.s = DetermineSign(a, b, "+")
; Убираем знаки из чисел
If Left(a, 1) = "-"
a = Right(a, Len(a) - 1)
EndIf
If Left(b, 1) = "-"
b = Right(b, Len(b) - 1)
EndIf
; Если знак результата требует вычитания
If signResult = "subtract"
ProcedureReturn SubtractLongNumbers(a, b)
ElseIf signResult = "subtract_reverse"
ProcedureReturn SubtractLongNumbers(b, a)
EndIf
; Выполняем сложение
Protected carry = 0
Protected result.s = ""
Protected i, j, sum, digitA, digitB
; Выравниваем числа по десятичной точке
Protected aPoint = FindString(a, ".", 1)
Protected bPoint = FindString(b, ".", 1)
If aPoint = 0
a + ".0"
aPoint = Len(a) - 1
EndIf
If bPoint = 0
b + ".0"
bPoint = Len(b) - 1
EndIf
; Выравниваем дробные части
While Len(a) - aPoint < Len(b) - bPoint
a + "0"
Wend
While Len(b) - bPoint < Len(a) - aPoint
b + "0"
Wend
; Выравниваем целые части
While aPoint < bPoint
a = "0" + a
aPoint + 1
Wend
While bPoint < aPoint
b = "0" + b
bPoint + 1
Wend
; Складываем цифры справа налево
For i = Len(a) To 1 Step -1
If Mid(a, i, 1) = "."
result = "." + result
Continue
EndIf
digitA = Val(Mid(a, i, 1))
digitB = Val(Mid(b, i, 1))
sum = digitA + digitB + carry
carry = sum / 10
result = Str(sum % 10) + result
Next
If carry > 0
result = Str(carry) + result
EndIf
; Добавляем знак результата
If signResult = "-1"
result = "-" + result
EndIf
ProcedureReturn result
EndProcedure
Procedure.s MultiplyLongNumbers(a.s, b.s)
Protected signResult.s = DetermineSign(a, b, "*")
; Убираем знаки из чисел
If Left(a, 1) = "-"
a = Right(a, Len(a) - 1)
EndIf
If Left(b, 1) = "-"
b = Right(b, Len(b) - 1)
EndIf
; Убираем десятичные точки и запоминаем количество знаков после точки
Protected aPoint = FindString(a, ".", 1)
Protected bPoint = FindString(b, ".", 1)
If aPoint > 0
a = RemoveString(a, ".")
aDecimalPlaces = Len(a) - aPoint + 1
Else
aDecimalPlaces = 0
EndIf
If bPoint > 0
b = RemoveString(b, ".")
bDecimalPlaces = Len(b) - bPoint + 1
Else
bDecimalPlaces = 0
EndIf
; Умножаем числа как целые
Protected result.s = "0"
Protected i, j, carry, product
Protected temp.s
For i = Len(b) To 1 Step -1
carry = 0
temp = ""
For j = Len(a) To 1 Step -1
product = Val(Mid(a, j, 1)) * Val(Mid(b, i, 1)) + carry
carry = product / 10
temp = Str(product % 10) + temp
Next
If carry > 0
temp = Str(carry) + temp
EndIf
; Сдвигаем результат влево на соответствующее количество разрядов
temp + String("0", Len(b) - i)
result = AddLongNumbers(result, temp)
Next
; Вставляем десятичную точку
Protected totalDecimalPlaces = aDecimalPlaces + bDecimalPlaces
If totalDecimalPlaces > 0
; Если количество десятичных разрядов больше длины результата, добавляем ведущие нули
If totalDecimalPlaces > Len(result)
result = String("0", totalDecimalPlaces - Len(result)) + result
EndIf
; Вставляем точку
result = Left(result, Len(result) - totalDecimalPlaces) + "." + Right(result, totalDecimalPlaces)
EndIf
; Убираем ведущие нули
While Left(result, 1) = "0" And Len(result) > 1 And Mid(result, 2, 1) <> "."
result = Right(result, Len(result) - 1)
Wend
; Убираем лишние нули после точки
If FindString(result, ".", 1) > 0
While Right(result, 1) = "0"
result = Left(result, Len(result) - 1)
Wend
If Right(result, 1) = "."
result = Left(result, Len(result) - 1)
EndIf
EndIf
; Добавляем знак результата
If signResult = "-1"
result = "-" + result
EndIf
ProcedureReturn result
EndProcedure
a.s = "123.456"
b.s = "78.98765"
Debug "Произведение: " + MultiplyLongNumbers(a, b)
Debug ValD(a)*ValD(b)Чё-то я где-то тут не допираю - умножает нормально но точка в числе стоит не там, как исправить?