UTNianos

Versión completa: algoritmo para logaritmos
Actualmente estas viendo una versión simplificada de nuestro contenido. Ver la versión completa con el formato correcto.
en base a una consulta por ahí de cómo calcular logaritmos a mano, me puse a investigar un poco y se me ocurrió hacer un pequeño algoritmo que calcule el logaritmo de un número, usando mi lenguaje predilecto.

si se animan pueden testearlo o poner algoritmos en otros lenguajes.



| funcCaract funcMant logaritmo logaritmoNeperiano logaritmoNatural precision |

precision := 3.

funcCaract := [:b :a :c :f | | cc |
cc := c.
(a < b)
ifTrue: [
(a < 1)
ifTrue: [f valueWithArguments: (Array with: b with: (a raisedTo: -1) with: c with: f)]
ifFalse: [Array with: cc with: a]]
ifFalse: [cc := f valueWithArguments: (Array with: b with: (a/b) with: c+1 with: f)]].

funcMant := [:b :r :m :p :c :f |
(p > 0) ifTrue: [
(r < b)
ifTrue: [m at: p put: c.
f valueWithArguments: ((OrderedCollection new) add: b; add: (r raisedTo: 10); add: m; add: (p-1); add: 0; add: f; yourself) asArray]
ifFalse: [f valueWithArguments: ((OrderedCollection new) add: b; add: (r/b); add: m; add: p; add: c+1; add: f; yourself) asArray]].
m].

logaritmo := [:base :argumento | | caracteristica mantisaCalc mantisa result |
caracteristica := 0.
mantisaCalc := 0.
mantisa := (Array new: precision+2) atAllPut: 0; yourself.
(argumento <= 0) ifTrue: [Error signal: 'el argumento debe ser positivo'].
(argumento = 1)
ifFalse: [(argumento = base)
ifTrue: [caracteristica := 1]
ifFalse: [result := funcCaract valueWithArguments: (Array with: base with: argumento with: 0 with: funcCaract).
caracteristica := result at: 1.
result := funcMant valueWithArguments: ((OrderedCollection new) add: base; add: ((result at: 2) raisedTo: 10); add: mantisa; add: precision+2; add: 0; add: funcMant; yourself) asArray]].
mantisa reverse doWithIndex: [:dec :i | mantisaCalc := mantisaCalc + (dec / (10 raisedTo: i))].
(((caracteristica + mantisaCalc) roundTo: (10 raisedTo: precision negated)) * ((argumento < 1) ifTrue: [-1] ifFalse: [1])) asFloat ].

logaritmoNeperiano := [:argumento | logaritmo value: Float e value: argumento ].
logaritmoNatural := [:argumento | logaritmo value: 10 value: argumento ].

"-- pruebas --"
Transcript cr; show: 'log 30 = '; show: (logaritmo value: 10 value: 30) printString.
Transcript cr; show: 'log 5 = '; show: (logaritmoNatural value: 5) printString.
Transcript cr; show: 'log 10 = '; show: (logaritmoNatural value: 10) printString.
Transcript cr; show: 'ln e = '; show: (logaritmoNeperiano value: Float e) printString.


bueno, después de muchas pruebas en el entorno del foro, logré hacerlo funcionar.

me tiraba errores por todos lados, al parecer está bastante limitada la implementación, pero finalmente lo logré.

si le aumentan la precisión, o si utilizan un argumento muy grande, no van a conseguir resultados acá porque la recursión es muy grande y hace que se rompa. pero en un IDE en serio (como pharo) pueden probar números enormes con una gran precisión.



Transcript show: 50 ln printString


+10
Muy bueno! Está programado en SmallTalk no?
(17-08-2015 14:53)Joke escribió: [ -> ]Muy bueno! Está programado en SmallTalk no?

así es.
URLs de referencia