CLASS TBigInteger //FROM TGeneric
DATA cNumero
METHOD New( ) CONSTRUCTOR
METHOD Add()
METHOD Suma2()
METHOD SumaN()
METHOD Subtract()
METHOD Resta2()
METHOD RestaN()
METHOD Multiply()
METHOD Multiplica2()
METHOD MultiplicaN()
METHOD Divide() VIRTUAL
METHOD Potencia()
METHOD PotenciaN()
METHOD ToHex()
ENDCLASS
//------------------------------------------------//
METHOD New( cNumero ) CLASS TBigInteger
::cNumero := cValToChar(cNumero)
return Self
//------------------------------------------------//
METHOD Add( cNumero ) CLASS TBigInteger
::cNumero := ::SumaN({::cNumero, cNumero})
Return ::cNumero
//------------------------------------------------//
METHOD Suma2( cNumero1, cNumero2 ) CLASS TBigInteger
return ::SumaN({cNumero1, cNumero2})
//------------------------------------------------//
METHOD SumaN( aNumeros ) CLASS TBigInteger
Local n
Local m
Local k
Local i
Local cRes
Local cResto
Local cTotal
n := Len(aNumeros)
For k := 1 To n
aNumeros[k] = RTrim(aNumeros[k])
Next
// m será el número de mayor longitud
m := 0
For k := 1 To n
If Len(aNumeros[k]) > m
m = Len(aNumeros[k])
Endif
Next
For k := 1 To n
aNumeros[k] = PadL(aNumeros[k], m, " ")
Next
// sumar las filas obtenidas
cRes = ""
cResto = "0"
cTotal = ""
For k := m To 1 Step -1
cRes = cResto
For i = 1 To n
cRes = cValToChar(Val(cRes) + Val(/*"0" + */SubStr(aNumeros[i], k, 1)))
Next
cTotal = Right(cRes, 1) + cTotal
If Len(cRes) - 1 < 1
cResto = "0"
Else
cResto = Left(cRes, Len(cRes) - 1)
End
Next
//If cResto <> "0"
If !(cResto == "0")
cTotal = cResto + cTotal
End
cTotal := StrTran(LTrim(StrTran(cTotal,"0"," "))," ","0")
Return cTotal
//------------------------------------------------//
METHOD Subtract( cNumero ) CLASS TBigInteger
::cNumero := ::Resta2( ::cNumero, cNumero )
Return ::cNumero
//------------------------------------------------//
METHOD Resta2( cNumero1, cNumero2 ) CLASS TBigInteger
Local k
Local m
local cSigno
Local cRes
Local cResto
Local cPresto
Local cTotal
//quitamos ceros por delante y espacios de atras
cNumero1 := StrTran(LTrim(StrTran(RTrim(cNumero1),"0"," "))," ","0")
cNumero2 := StrTran(LTrim(StrTran(RTrim(cNumero2),"0"," "))," ","0")
m := Len(cNumero1)
If Len(cNumero1) < Len(cNumero2)
m := Len(cNumero2)
cNumero1 = PadL(cNumero1, m, " ")
elseIf Len(cNumero2) < Len(cNumero1)
cNumero2 = PadL(cNumero2, m, " ")
endif
// Poner el mayor(más largo) como primer número
cSigno := ""
if cNumero1 < cNumero2 //comparacion de strings: valido siempre y cuando los string sean del mismo tamaño
cSigno := "-"
swap(@cNumero1,@cNumero2)
endif
// cRestar las filas obtenidas
cRes = ""
cResto = "0"
cPresto = "0"
cTotal = ""
For k := m To 1 Step -1
cRes = cValToChar(Val(/*"0" + */SubStr(cNumero1, k, 1)) - Val(cPresto) - (Val(/*"0" + */SubStr(cNumero2, k, 1)) + Val(cResto)))
If Val(cRes) < 0
cRes = cValToChar(Val(cRes) + 10)
cPresto = "1"
else
cPresto = "0"
End
cTotal = Right(cRes, 1) + cTotal
If Len(cRes) - 1 < 1
cResto = "0"
Else
cResto = Left(cRes, Len(cRes) - 1)
End
Next
//If cResto <> "0"
If !(cResto == "0")
cTotal = cResto + cTotal
End
cTotal := StrTran(LTrim(StrTran(cTotal,"0"," "))," ","0")
Return cSigno + cTotal
//------------------------------------------------//
METHOD RestaN( aNumeros ) CLASS TBigInteger
Local i
Local cTotal
cTotal = aNumeros
For i = 2 To Len(aNumeros)
cTotal = ::Resta2(cTotal, aNumeros[i])
Next
Return cTotal
//------------------------------------------------//
METHOD Multiply( cNumero ) CLASS TBigInteger
::cNumero := ::Multiplica2( ::cNumero, cNumero )
Return ::cNumero
//------------------------------------------------//
METHOD Multiplica2( cNumero1, cNumero2) CLASS TBigInteger
Local n
Local i
Local k
Local j
Local c1
Local c2
Local cResto
Local cRes
local aNumeros
//quitamos ceros por delante y espacios de atras
cNumero1 := StrTran(LTrim(StrTran(RTrim(cNumero1),"0"," "))," ","0")
cNumero2 := StrTran(LTrim(StrTran(RTrim(cNumero2),"0"," "))," ","0")
// Poner el más largo como primer número
If Len(cNumero2) > Len(cNumero1)
swap(@cNumero1, @cNumero2)
End
// El número de operaciones necesarias
// será la cantidaNumeros de cifras del más pequeño
aNumeros:=Array(Len(cNumero2))//ReDim aNumeros(Len(cNumero2) - 1)
n = 0
cResto = "0"
cRes = ""
// Multiplicar formando filas con los cResultaNumerosos (al estilo manual)
For i := Len(cNumero2) To 1 Step -1
n = n + 1
aNumeros[n] = ""
// AñaNumerosir espacios(ceros) a la derecha según la cifra (fila) que se procese
For k = 2 To n
aNumeros[n] = aNumeros[n] + "0"
Next
c1 = substr(cNumero2, i, 1)
// Para simplificar las cosas
// se comprueba si se multiplicará por cero o por uno
// de forma que no sea necesario hacer estas operaciones
If c1 = "0"
aNumeros[n] = Replicate("0", Len(cNumero1)) + aNumeros[n]
ElseIf c1 = "1"
aNumeros[n] = cNumero1 + aNumeros[n]
Else
For j := Len(cNumero1) To 1 Step -1
c2 = Substr(cNumero1, j, 1)
cRes = cValToChar(Val(/*"0" +*/ c1) * Val(/*"0" +*/ c2) + Val(cResto))
aNumeros[n] = Right(cRes, 1) + aNumeros[n]
//If Len(cRes) - 1 < 1
If Len(cRes) = 1
cResto = "0"
Else
cResto = Left(cRes, Len(cRes) - 1)
End
Next
If cResto <> "0"
aNumeros[n] = cResto + aNumeros[n]
cResto = "0"
End
End
Next
Return ::SumaN( aNumeros )
//------------------------------------------------//
METHOD MultiplicaN( aNumeros ) CLASS TBigInteger
Local i
Local cTotal
cTotal = aNumeros[1]
For i = 2 To Len(aNumeros)
cTotal = ::Multiplica2(cTotal, aNumeros[i])
Next
Return cTotal
//------------------------------------------------//
METHOD Potencia( cElevado ) CLASS TBigInteger
::cNumero := ::PotenciaN( ::cNumero, cElevado )
Return ::cNumero
//------------------------------------------------//
METHOD PotenciaN(cNumero , cElevado ) CLASS TBigInteger
Local n
Local k
Local aNumeros
local cResultado
do case
case Val(cElevado)=0
cResultado := "1"
case Val(cElevado)=1
cResultado := cNumero
otherwise
n := Val(cElevado)
aNumeros := Array(n)
For k = 1 To n
aNumeros[k] = cNumero
Next
cResultado := ::MultiplicaN( aNumeros )
endcase
Return cResultado
//------------------------------------------------//
METHOD ToHex( ) CLASS TBigInteger
local i
local cPotencias2
local cResto
local cBin
::cNumero := StrTran(LTrim(StrTran(RTrim(::cNumero),"0"," "))," ","0")
cPotencias2 := PadL("",Len(::cNumero))
i:=0
Do While cPotencias2 < ::cNumero
cPotencias2 := Padl(::PotenciaN("2",cValToChar(i)),len(::cNumero))
i++
enddo
i -= 2
cResto := ::Resta2(::cNumero, ::PotenciaN("2",cValToChar(i)))
cBin := "1"
Do While i >0
i--
cPotencias2 := ::PotenciaN("2",cValToChar(i))
If Len(cPotencias2)<Len(cResto)
cPotencias2:=PadL(cPotencias2,Len(cResto))
else
If Len(cPotencias2)>Len(cResto)
cResto:=PadL(cResto,Len(cPotencias2))
endif
endif
if cPotencias2 <= cResto
cResto := ::Resta2(cResto, cPotencias2)
cBin := cBin+"1"
else
cBin := cBin+"0"
endif
enddo
return cBinToHexN(cBin)
Static Function swap(u,v)
Local t
t = u
u = v
v = t
Return NIL