Foros del Web » Programación para mayores de 30 ;) » Programación General »

[SOLUCIONADO] Problema con decimales.

Estas en el tema de Problema con decimales. en el foro de Programación General en Foros del Web. Por ejemplo esto: Código: Act = 0; do { Act = Act+0.1; } while ( Act < 0.9 ); Termina con Act siendo 1, pero ...
  #1 (permalink)  
Antiguo 01/09/2015, 19:13
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Problema con decimales.

Por ejemplo esto:
Código:
Act = 0;
do {
	Act = Act+0.1;
} while ( Act < 0.9 );
Termina con Act siendo 1, pero eso no debería ocurrir, debería terminar en 0.9.

Inicia siendo 0, luego:
0.1
¿es < 0.9?
Sí, entonces pasa a ser 0.2
así sucesivamente hasta 0.9
¿es < 0.9?
No, sin embargo debido al error que digo se aplica el proceso de nuevo y pasa a ser 1.

Es como si el programa dijera que es 0.9 por simplificar pero en realidad fuese 0.899999 cosa que ya me ha pasado.

Postearé en otros sitios y buscaré experiencias que haya tenido con esto -será más fácil hallarlas en Internet que en mi mente xD -, mientras si saben me pueden dar una solución.

Gracias.
  #2 (permalink)  
Antiguo 01/09/2015, 19:30
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Lo que encontré no me soluciona, sería "transformar los decimales en enteros", pero hacer eso me complicaría, prefiero algo más sencillo ¿ideas?
  #3 (permalink)  
Antiguo 02/09/2015, 00:34
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 10 años, 3 meses
Puntos: 182
Respuesta: Problema con decimales.

Buenas,

Te has dado cuenta de que ni siquiera has indicado de que lenguaje de programacion se trata?


Un saludo
__________________
If to err is human, then programmers are the most human of us
  #4 (permalink)  
Antiguo 02/09/2015, 08:07
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Pensé que era irrelevante para algo como esto que parece tan común y silvestre -es un do while en que se modifica una variable, es una de las cosas más simples y comunes de la programación o de la casi programación-, pero de hecho no sé cual es, es Action Script pero el que se usa en Macromedia Flash 5, o sea no sé si es el "común" 1.0, si con cada versión vieja de Flash le han cambiado cosas...
  #5 (permalink)  
Antiguo 02/09/2015, 11:07
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 10 años, 3 meses
Puntos: 182
Respuesta: Problema con decimales.

Buenas,

Tienes razon, de hecho he reproducido tu mismo ejemplo en otros lenguajes dinamicos como JavaScript o Python.

Tienes que tener en cuenta que las maquinas no calculan como nosotros, sino que realizan aproximaciones y en algun caso la precision en coma flotante nos juega malas pasadas.
https://en.wikipedia.org/wiki/IEEE_754-1985

Tanto en Python como en JavaScript existen soluciones para lidiar con estos casos en los que dependemos de la precision.
No conozco ActionScript pero supongo que tambien hay soluciones. Por lo pronto, veo que existe un metodo toPrecision() que puede servir.
http://help.adobe.com/en_US/FlashPla.../3/Number.html

Un saludo
__________________
If to err is human, then programmers are the most human of us
  #6 (permalink)  
Antiguo 03/09/2015, 14:20
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 14 años, 5 meses
Puntos: 73
Respuesta: Problema con decimales.

Hace algún tiempo respondí a un post en el que se planteaba un problema similar al tuyo:

http://www.forosdelweb.com/f96/valid...7/#post4153049

Quizá puedas hacerte idea de lo que está pasando.

Saludos,
  #7 (permalink)  
Antiguo 04/09/2015, 18:11
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

De momento tengo:
Código:
Act = 0;
ActDec = 1;
do {
    Act = (Act*(Math.pow(10, ActDec))+1)/(Math.pow(10, ActDec));
    trace (Act);
} while (Act<0.9);
if (Act > 0.9) {
    trace ("Sí");
}
O sea sí, decidí convertir a enteros antes de realizar las operaciones, pero igual falla.

ActDec marca cuánto se suma en realidad. Antes se sumaba 0.1, acá también, pero con este sistema intenté que cualquier decimal pudiera sumarse como si fuese entero. Los números que se usan dependen de cómo se configure una pantalla, algunas como ActDec=0, sumarle 1 y pretender que sea < 0.9 no tienen sentido, pero eso sería un error de cómo o para qué se usa el sistema, no un error del sistema en sí. Lo que hace en este caso es multiplicar Act*10, sumarle 1, y luego dividir entre 10. Entonces es como si sumara 0.1. Para sumar 0.01 o cualquier número con 2 decimales, lo de multiplicar y dividir entre 10 se haría 2 veces. Sí, ActDec marca la cantidad de decimales y de veces que se repetirá esa operación.
Funciona mejor parece, cuando termina el do while dice que Act es 0.9, pero con el if al final me dice que en realidad es mayor que eso. Lo bueno es que, aparentemente, es tan poco mayor, que no lo toma como 1, o sea ha mejorado, pero la idea es lograr más exactitud.

Math.pow (X, Y) eleva X Y veces. Potencia.

Trace simplemente muestra en pantalla algo que se le indique.

Profesor_Falken:
Mi Flash no tiene toPrecision, muestro a todos lo que tiene a ver si lo entienden porque yo mucho no, por ejemplo "valueOf".
  #8 (permalink)  
Antiguo 04/09/2015, 18:12
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Cita:
Number (objeto)
El objeto Number es un objeto envolvente sencillo para el tipo de datos número, lo que quiere decir que puede manipular valores numéricos primitivos utilizando los métodos y propiedades asociadas con el objeto Number. La funcionalidad proporcionada por este objeto es idéntica a la del objeto Number de JavaScript.

Debe utilizar el constructor Number cuando llama a los métodos del objeto Number, pero no necesita utilizar el constructor cuando llama a las propiedades del objeto Number. El ejemplo siguiente especifica la sintaxis para llamar a los métodos y propiedades del objeto Number.

A continuación se muestra un ejemplo de llamada al método toString del objeto Number:

myNumber = new Number(1234);

myNumber.toString();
Devuelve una cadena que contiene la representación binaria del número 1234.

A continuación se muestra un ejemplo de llamada a la propiedad MIN_VALUE (también denominada constante) del objeto Number:

smallest = Number.MIN_VALUE


Resumen de los métodos del objeto Number
Método Descripción
toString

Devuelve la representación de cadena de un

objeto Number.

valueOf

Devuelve el valor primitivo de un objeto Number.





Resumen de las propiedades de un objeto Number
Propiedad Descripción
MAX_VALUE

Constante que representa el número mayor que se puede representar (IEEE-754 de doble precisión). Este número es aproximadamente 1.7976931348623158e+308.

MIN_VALUE

Constante que representa el número menor que se puede representar (IEEE-754 de doble precisión). Este número es aproximadamente 5e-324.

NaN

Constante que representa el valor de Not a Number (NaN).

NEGATIVE_INFINITY

Constante que representa el valor de infinito negativo.

POSITIVE_INFINITY

Constante que representa el valor de infinito positivo. Este valor es el mismo que la variable global Infinity.





Constructor del objeto Number.

Sintaxis

myNumber = new Number(valor);

Argumentos

valor El valor numérico del objeto Number que se está creando o un valor que se va a convertir en un número.

Descripción

Constructor; crea un nuevo objeto Number. Debe utilizar el constructor Number cuando utilice los métodos toString y valueOf del objeto Number. No se usa un constructor cuando se utilizan la propiedades del objeto Number. El constructor new Number se utiliza fundamentalmente como marcador de lugar. Una instancia del objeto Number no es lo mismo que la función Number que convierte un argumento en un valor primitivo.

Reproductor

Flash 5 o posterior.

Ejemplo

El código siguiente construye nuevos objetos Número.

n1 = new Number(3.4);
n2 = new Number(-10);
  #9 (permalink)  
Antiguo 04/09/2015, 18:14
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Algunas cosas salen con mala sangría porque están en una tabla, no las puedo copiar bien

Cita:
Math (objeto)
El objeto Math es un objeto de nivel superior al que puede acceder sin utilizar un constructor.

Utilice los métodos y propiedades de este objeto para acceder y manipular constantes y funciones matemáticas. Todas las propiedades y métodos del objeto Math son estáticos y deben llamarse utilizando la sintaxis Math.method(argumento) o Math.constant. En ActionScript, las constantes se definen con la máxima precisión de números con coma flotante IEEE-754 de doble precisión.

El objeto Math está admitido por completo en Flash Player 5. En Flash Player 4, los métodos del objeto Math funcionan, pero se emulan usando aproximaciones y es posible que no sean tan precisos como las funciones matemáticas no emuladas que soporta Flash Player 5.

Algunos de los métodos del objeto Math toman el radián de un ángulo como argumento. Puede utilizar la ecuación siguiente para calcular valores de radianes o sencillamente pase la ecuación (introduciendo un valor para grados) para el argumento radián.

Para calcular un valor de radián, utilice esta fórmula:

radián = Math.PI/180 * grado
A continuación se muestra un ejemplo de pasar una ecuación como argumento para calcular el seno de un ángulo de 45 grados:

Math.SIN(Math.PI/180 * 45) es lo mismo que Math.SIN(.7854)



Resumen de los métodos del objeto Math
Método Descripción
abs

Calcula un valor absoluto.

acos

Calcula un arco coseno.

asin

Calcula un arco seno.

atan

Calcula un arco tangente.

atan2

Calcula un ángulo desde el eje x hasta el punto.

ceil

Redondea un número al entero más cercano hacia arriba.

cos

Calcula un coseno.

exp

Calcula un valor exponencial.

floor

Redondea un número al entero más cercano hacia abajo.

log

Calcula un logaritmo natural.

max

Devuelve el mayor de dos números enteros.

min

Devuelve el menor de dos números enteros.

pow

Calcula x elevado a la potencia de y.

aleatorio

Devuelve un número seudoaleatorio ente 0,0 y 1,1.

round

Redondea al número entero más cercano.

sin

Calcula un seno.

sqrt

Calcula una raíz cuadrada.

tan

Calcula una tangente.





Resumen de las propiedades de un objeto Math

Todas las propiedades del objeto Math son constantes.
Propiedad Descripción
E

La constante de Euler y la base de los logaritmos naturales (aproximadamente 2,718).

LN2

El logaritmo natural de 2 (aproximadamente 0, 693).

LOG2E

El logaritmo en base 2 de e (aproximadamente 1,442).

LN10

El logaritmo natural de 10 (aproximadamente 2, 302).

LOG10E

El logaritmo en base 10 de e (aproximadamente 0,434).

PI

La relación entre la circunferencia de un círculo y su diámetro (aproximadamente 3,14159).

SQRT1_2

El recíproco de la raíz cuadrada de 1/2 (aproximadamente 0, 707).

SQRT2

La raíz cuadrada de 2 (aproximadamente 1,414).
  #10 (permalink)  
Antiguo 04/09/2015, 18:23
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Fw190, supuestamente la variable se define mediante double, es automático...

De momento tengo pensado esto:
- Probar quitar decimales.
- Pensar una alternativa (o sea hacer el programa de otra forma, como para no tener que hacer un do whiles como ese).
- Usar while en vez de Do while. No sabía que existía, puede ayudar.
- Probar definir el nro mediante 2 variables. 1) La parte entera. 2) La parte decimal. No sé bien cómo programaría las operaciones matemáticas, tendría que pensarlo.
- Probar el mismo proceso que usé pero el . agregarlo como si fuese un string. Luego lo convierto a número con los dedos cruzados para que quede bien xD
  #11 (permalink)  
Antiguo 04/09/2015, 20:59
(Desactivado)
 
Fecha de Ingreso: enero-2015
Mensajes: 393
Antigüedad: 9 años, 10 meses
Puntos: 52
Respuesta: Problema con decimales.

Ok, te tiro un par de sogas:

Logré reproducir tu problema en .Net 4.5.2 con F# 4.0. Básicamente, como te indicaron arriba, es un problema muy común en casi todos los lenguajes de programación, debido a la forma en la que el CPU hace los cálculos de punto flotante.

El siguiente código F#:

Código F#:
Ver original
  1. open System
  2.  
  3. [<EntryPoint>]
  4. let main argv =
  5.     let mutable i = 0.0
  6.     while i < 0.9 do
  7.         i <- i + 0.1
  8.         Console.WriteLine(i)
  9.     Console.ReadLine() |> ignore
  10.     0

devuelve este resultado:

0,10000000000000001
0,20000000000000001
0,30000000000000004
0,40000000000000002
0,5
0,59999999999999998
0,69999999999999996
0,79999999999999993
0,89999999999999991
0,99999999999999989

Ahí se pueden ver claramente los errores de precisión, y la causa del problema: al llegar a la 9na iteración, se está comparando el valor 0.89999999999999991, el cuál es menor a 9, con lo cuál el código se ejecuta una vez más, llegando a 0,99999999999999989.

Googleando rápidamente (otra habilidad muy necesaria para ser programador), encontré esto:

http://stackoverflow.com/questions/6...541929#1541929

Cita:
Iniciado por Dicho sea de paso
Nótese que nunca jamás he usado ActionScript en mi vida, y aún así pude encontrar una solución a este problema. Esas son las cosas que necesitás practicar.
En ese post hay una sugerencia:

Código ActionScript:
Ver original
  1. var setPrecision:Function = function(number:Number, precision:int) {
  2.  precision = Math.pow(10, precision);
  3.  return Math.round(number * precision)/precision;
  4. }

es una función que redondea el valor que le pases en el primer parámetro, a la cantidad de decimales que le pases segundo parámetro, por ejemplo:

Código ActionScript:
Ver original
  1. var number:Number = 10.98813311;
  2. trace(setPrecision(number,1)); //Result is 10.9
  3. trace(setPrecision(number,2)); //Result is 10.98
  4. trace(setPrecision(number,3)); //Result is 10.988 and so on

Hay otros comentarios, por ejemplo uno que dice que esta misma función fue incorporada en ActionScript 3.0, con lo cuál deberías poder usarlo, si al menos estuvieras en una versión más actualizada de esa plataforma.

Después vi esto: https://code.google.com/p/bigdecimal/ que básicamente es un port a ActionScript del tipo BigDecimal de java, pero me llamó muchísimo el comentario del tipo:

Cita:
So for all of you in financials, NEVER USE FLEX OR FLASH to compute data. Seriously guys. DONT use that technology. It is the worst thing that ever existed in the world.
Que traducido es algo así como:

Cita:
Así que para todos lo que estén en finanzas, NUNCA USEN FLEX NI FLASH para computar daros. En serio muchachos. NO usen esa technología. Es lo peor que alguna vez existió en el mundo.
Seguido de un montón de otras quejas de deficiencias en esa plataforma, que no vienen al caso...

Curioso no?

Nótese que en las plataformas serias hay implementaciones de tipos numéricos decimales (decimal en .Net, BigDecimal en java) que no tienen este problema ya que están pensados justamente para representar números decimales.

Por ejemplo, el problema se soluciona en .Net usando el tipo decimal, cambiando los literales numéricos, usando la "m" que es el sufijo que indica tipos decimales en .Net:

Código F#:
Ver original
  1. let mutable i = 0m
  2.     while i < 0.9m do
  3.         i <- i + 0.1m

Y por supuesto ya que estamos usando F# podemos reemplazar ese while horrible y procedural por un for sobre un literal de lista, quitar la variable mutable, y cambiar el Console.WriteLine por printf:

Código F#:
Ver original
  1. open System
  2.  
  3. [<EntryPoint>]
  4. let main argv =
  5.     for i in 0m .. 0.1m .. 0.9m do
  6.         printf "%M " i
  7.     Console.ReadLine() |> ignore
  8.     0

O incluso algo mucho más idiomático y propio de un lenguaje funcional:

Código F#:
Ver original
  1. open System
  2.  
  3. [<EntryPoint>]
  4. let main argv =
  5.     let print(x) = printf "%M " x
  6.     [0m .. 0.1m .. 0.9m]
  7.     |> Seq.map(print) |> ignore
  8.     Console.ReadLine() |> ignore
  9.     0

Última edición por agleiva; 04/09/2015 a las 22:01
  #12 (permalink)  
Antiguo 05/09/2015, 21:28
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Cita:
Iniciado por agleiva Ver Mensaje
Googleando rápidamente (otra habilidad muy necesaria para ser programador)
Vale, si eso es cierto entonces soy un mal programador...

Código ActionScript:
Ver original
  1. var setPrecision:Function = function(number:Number, precision:int) {
  2.  precision = Math.pow(10, precision);
  3.  return Math.round(number * precision)/precision;
  4. }
Buena idea, Math.round recuerdo que hace tiempo preferí no usarlo, no sé bien por qué pero probablemente que era poco confiable en el sentido de que no se sabe bien si baja o sube el número. Ayer probé esto:
Código a:
Ver original
  1. Act = 0;
  2. ActDec = 1;
  3. do {
  4.     Act = (Math.floor((Act*(Math.pow(10, ActDec))+1)))/(Math.pow(10, ActDec));
  5.     trace (Act);
  6. } while (Act<0.9);
  7. if (Act>0.9) {
  8.     trace ("Sí");
  9. }

Math.floor es similar a round, quita los decimales pero sin el riesgo de que el número aumente.

Pero no, no funciona, al final aparece el Sí marcando que Act>0.9 a pesar de que el último número que muestra la pantalla es 0.9. Sin duda el programa que usás es mejor en ese sentido porque te muestra los números que realmente son. Capáz que acá se puede también, creando un texto dinámico en la pantalla, pero como trace es más rápido de hacer...

Por cierto he probado round con eso y tampoco funciona ¿lo implementé mal?

Código b:
Ver original
  1. Act = 0;
  2. ActDec = 1;
  3. do {
  4.     Precision = Math.pow(10, ActDec);
  5.     Act = Math.round(Act*Precision+1)/Precision;
  6.     trace (Act);
  7. } while (Act<0.9);
  8. if (Act>0.9) {
  9.     trace ("Sí");
  10. }

Nop... sigue apareciendo el Sí.

Cita:
Hay otros comentarios, por ejemplo uno que dice que esta misma función fue incorporada en ActionScript 3.0, con lo cuál deberías poder usarlo, si al menos estuvieras en una versión más actualizada de esa plataforma.
Y sino también, si me acabas de dar la versión "vieja". ¿O no?

Si no lo has hecho y te interesa, fijate cómo "incorporaron" el fscommand save a partir de Flash 6 o lo que sea -en el 8 no está, y no hablo de Adobe-.

Y me hiciste acordar esto:
http://sofosagora.net/offtopic-gener...0.html#p114949
xD

Cita:
Que traducido es algo así como:
Así que para todos lo que estén en finanzas, NUNCA USEN FLEX NI FLASH para computar daros. En serio muchachos. NO usen esa technología. Es lo peor que alguna vez existió en el mundo.
Buena traducción. A mí ya no me llaman la atención las exageraciones, al contrario, me aburren.

Cita:
Curioso no?
Nah... es muy común.

Cita:
usando F# podemos reemplazar ese while horrible y procedural por un for sobre un literal de lista, quitar la variable mutable, y cambiar el Console.WriteLine por printf:
Eso me da curiosidad ¿por qué dices que el while es horrible? Yo el for nunca lo entendí, es decir, siempre me pareció más complicado que el "dow" pero muy similar, así que le dediqué muy poca atención.

...

Bueno, hoy he estado pensando en hacer la división entre 10 mediante strings, o sea mover el . hacia la izquierda y agregar la cantidad debida de 0s. No he podido idear el código para eso, quizá porque estaba confundido -largo de explicar-, pero me aclaré ya -creo-.

Esta tabla muestra el resultado (NewAct) dependiendo de otras 2 variables (Act y ActDec):
(Nota: N significa "cualquier valor").
Act_____ActDec_____NewAct
0_________N__________0

N_________0__________N

0.1_______1__________0.01
2_________1__________0.2
30________1__________3
El . se mueve 1 lugar hacia la izquierda.

0.1_______N__________...
2_________N__________...
30________N__________...
El . se mueve N lugares hacia la izquierda.

Eso ¿cómo sería el código para eso? Aunque haya una solución más fácil quisiera saber esta respuesta también, por curiosidad. Voy a pensarlo.
  #13 (permalink)  
Antiguo 07/09/2015, 15:21
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Ya tengo bastante el pseudocódigo o como se llame para usar strings:
Código:
ActCifras = Contar cifras de Act
Si ActCifras > ActDec
    Insertar "." en Act (debo ver en qué parte).
sino si ActCifras == ActDec
    Act = Convertir a número("0."+Act)
sino (o sea si ActCifras < ActDec)
    Act = Convertir a número("0."+(Diferencia)"0"s+Act)
Pero antes de empezarlo a convertir en código analicé un poco más lo que tenía.

Esto:
Código a:
Ver original
  1. Act = 0;
  2. ActDec = 1;
  3. do {
  4.     Precision = Math.pow(10, ActDec);
  5.     Act1 = Act*Precision;
  6.     Act2 = Act1+1;
  7.     Act3 = Math.floor(Act2);
  8.     Act = Act3/Precision;
  9.     trace (Act1+" , "+Act2+" , "+Act3+" , "+Act);
  10. } while (Act<0.9);
  11. if (Act>0.9) {
  12.     trace ("Sí");
  13. }
Me da esto:
Cita:
0 , 1 , 1 , 0.1
1 , 2 , 2 , 0.2
2 , 3 , 3 , 0.3
3 , 4 , 4 , 0.4
4 , 5 , 5 , 0.5
5 , 6 , 6 , 0.6
6 , 7 , 7 , 0.7
7 , 8 , 8 , 0.8
8 , 9 , 9 , 0.9
Curiosidad enorme:
Precision es 10. Pero si cuando lo uso para dividir le pongo 10 en vez de Precision, el do while (¿bucle?) no termina, se repite esto:
3 , 4 , 3 , 0.3

Si uso Precision en la división y round en vez de floor, el bucle termina como el otro, el mismo error.

Si uso 10 en la división y round en vez de floor, no hay error.

Pero claro la precisión variará, yo no puedo poner 10 porque podría deber ser 100 en otro caso.

Por otro lado, con esto:
Código a:
Ver original
  1. Act = 0;
  2. ActDec = 1;
  3. do {
  4.     Act1 = Act*(Math.pow(10, ActDec))+1;
  5.     Act = Act1/10;
  6.     trace (Act1+" , "+Act);
  7. } while (Act<0.9);
  8. if (Act>0.9) {
  9.     trace ("Sí");
  10. }
Me muestra esto:
Cita:
1 , 0.1
2 , 0.2
3 , 0.3
4 , 0.4
5 , 0.5
6 , 0.6
7 , 0.7
8 , 0.8
8.99999999999999 , 0.899999999999999
9.99999999999999 , 0.999999999999999
O sea... entiendo que no usé round, pero al principio tampoco, y sin embargo con este código me muestra muchos decimales y con los otros códigos no ¿por qué será?
  #14 (permalink)  
Antiguo 07/09/2015, 15:34
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Esto:
Código a:
Ver original
  1. Act = 0;
  2. ActDec = 1;
  3. do {
  4.     Act1 = Act*(Math.pow(10, ActDec));
  5.     Act2 = Act1+1;
  6.     Act = Act2/10;
  7.     trace (Act1+" , "+Act2+" , "+Act);
  8. } while (Act<0.9);
  9. if (Act>0.9) {
  10.     trace ("Sí");
  11. }
Me da:
Cita:
0 , 1 , 0.1
1 , 2 , 0.2
2 , 3 , 0.3
3 , 4 , 0.4
4 , 5 , 0.5
5 , 6 , 0.6
6 , 7 , 0.7
7 , 8 , 0.8
7.99999999999999 , 8.99999999999999 , 0.899999999999999
8.99999999999999 , 9.99999999999999 , 0.999999999999999
Si cambio el /10 por /(Math.pow(10, ActDec)) me da números con pocos decimales, pero también me da error. No le veo mucho sentido pero parece que usar /Math.pow o usarlo 2 veces -aunque no sea /- hace que el trace muestre los números redondeados.
  #15 (permalink)  
Antiguo 07/09/2015, 15:57
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Lo claro es que la división falla, y así las soluciones que dimos no sirven. La transformación mediante strings tampoco sirve del todo, porque si continúo avanzando en el programa tendría que poder hacer bien divisiones entre 762.38 por ejemplo, es decir, no sólo /10.

Se me ocurre que podría evitar hacer procesos con decimales... No es necesario usarlos, pero como esto es para un programa que resuelva problemas -o sea que facilite la vida-, sería paradójico que hubiera que convertir manualmente a enteros y luego reconvertir a decimales... Pero quizá pueda automatizar eso... Voy a pensar.
  #16 (permalink)  
Antiguo 07/09/2015, 16:14
(Desactivado)
 
Fecha de Ingreso: enero-2015
Mensajes: 393
Antigüedad: 9 años, 10 meses
Puntos: 52
Respuesta: Problema con decimales.

Cita:
Iniciado por Tachikomaia Ver Mensaje
Lo claro es que la división falla, y así las soluciones que dimos no sirven. La transformación mediante strings tampoco sirve del todo, porque si continúo avanzando en el programa tendría que poder hacer bien divisiones entre 762.38 por ejemplo, es decir, no sólo /10.

Se me ocurre que podría evitar hacer procesos con decimales... No es necesario usarlos, pero como esto es para un programa que resuelva problemas -o sea que facilite la vida-, sería paradójico que hubiera que convertir manualmente a enteros y luego reconvertir a decimales... Pero quizá pueda automatizar eso... Voy a pensar.
AJAJAJ... es una broma verdad?

"se me ocurre que podría evitar hacer procesos con decimales" - AJJAJAJA.

Che, y si te buscás un lenguaje de programación que no sea una basura inservible y que te permita avanzar en lo que estás tratando de hacer sin toparte con una limitación cada 5 minutos? No se te ocurre?

Viste como lo resolví en F# agregando la "m"?
  #17 (permalink)  
Antiguo 07/09/2015, 16:18
(Desactivado)
 
Fecha de Ingreso: marzo-2012
Mensajes: 366
Antigüedad: 12 años, 7 meses
Puntos: 31
Respuesta: Problema con decimales.

ConvertirADecimal(ConvertirAEntero(NúmeroDecimal * 10^n))/10^n

(^n = elevado a n)

ConvertirADecimal(ConvertirAEntero(NúmeroDecimal * 10))/10:

Deja en 1 solo decimal (el exponente del 10) el número introducido.

0.51111 lo transforma en 0.5
0.59999 lo transforma en 0.5

ConvertirADecimal(ConvertirAEntero(NúmeroDecimal * 100))/100:

Deja en 2 decimales (el exponente del 10) el número introducido.

0.51111 lo transforma en 0.51
0.59999 lo transforma en 0.59

Última edición por Kritik; 07/09/2015 a las 16:24
  #18 (permalink)  
Antiguo 07/09/2015, 18:05
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Cita:
Iniciado por agleiva Ver Mensaje
AJAJAJ... es una broma verdad?

"se me ocurre que podría evitar hacer procesos con decimales" - AJJAJAJA.
No es broma, en principio pensé que no se podía, pero ahora no creo tenerlo tan tengo claro, debo pensarlo bien y también pensar qué tan difícil sería hacer la "evasión".
¿Tú qué crees? Si alguien te define un problema mediante valores decimales ¿serviría que los conviertas en enteros proporcionalmente? ¿en cualquier problema...?

Cita:
Che, y si te buscás un lenguaje de programación que no sea una basura inservible y que te permita avanzar en lo que estás tratando de hacer sin toparte con una limitación cada 5 minutos? No se te ocurre?
Quiero hacerlo con las herramientas que conozco, quizá aprender alguna, pero no mucho más si no es necesario.

Cita:
Viste como lo resolví en F# agregando la "m"?
Pero no quiero resolverlo así. ¿Viste mi pregunta sobre el while?
"Eso me da curiosidad ¿por qué dices que el while es horrible? Yo el for nunca lo entendí, es decir, siempre me pareció más complicado que el "dow" pero muy similar, así que le dediqué muy poca atención."
  #19 (permalink)  
Antiguo 07/09/2015, 18:20
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Kritik, podrías decirme si tu código es diferente a esto:
Código a:
Ver original
  1. Act = 0;
  2. ActDec = 1;
  3. do {
  4.     Precision = Math.pow(10, ActDec);
  5.     Act = Math.round(Act*Precision+1)/Precision;
  6.     trace (Act);
  7. } while (Act<0.9);
  8. if (Act>0.9) {
  9.     trace ("Sí");
  10. }

Parece lo mismo, pero me es complicado pensar lo tuyo, a ver:
ConvertirADecimal(ConvertirAEntero(NúmeroDecimal * 10^n))/10^n

Primero elevas 10 a la n, es lo que hago con la variable Precision (ActDec sería n).
Luego multiplicas eso por el número decimal en cuestión, es también lo que hago.
Después lo conviertes a entero. Yo antes le sumo 1 porque se lo debo sumar, pero también lo convierto en entero después, no hay diferencia. La diferencia podría ser la forma conque se convierte en entero (redondear hacia abajo, hacia arriba, etc), o que usas un programa en que se define el tipo de variable (yo no, es automático), pero en definitiva es lo mismo.
Posteriormente conviertes a decimal, cosa que supuestamente yo no requiero hacer.
Por último divides entre 10 a la n, lo mismo que hago, pero a mí la división me da mal, por ejemplo si es 9 me lo deja en 0.89999 o algo por el estilo, el caso es que al final del bucle dice que es > 0.9.
Fijate este mensaje:
http://www.forosdelweb.com/f14/probl...9/#post4740285
  #20 (permalink)  
Antiguo 07/09/2015, 18:38
(Desactivado)
 
Fecha de Ingreso: enero-2015
Mensajes: 393
Antigüedad: 9 años, 10 meses
Puntos: 52
Respuesta: Problema con decimales.

Cita:
Iniciado por Tachikomaia Ver Mensaje
¿Tú qué crees? Si alguien te define un problema mediante valores decimales ¿serviría que los conviertas en enteros proporcionalmente? ¿en cualquier problema...?
NO.

La verdad que me parece la peor idea que se te puede ocurrir.

Si tenés que realizar operaciones con números decimales usás un tipo numérico decimal. Usar punto flotante trae los problemas de redondeo (de los que ya hablamos), y hacer lo que vos planteás es innecesario, tedioso, poco práctico y muy propenso a errores, así que cuando queres manejar valores exactos usás decimal.

Cita:
Iniciado por Tachikomaia Ver Mensaje
Quiero hacerlo con las herramientas que conozco, quizá aprender alguna, pero no mucho más si no es necesario.
A ver si te queda claro: ESA BASURA DE ACTIONSCRIPT NO SIRVE PARA NADA.

No podés resolver un problema de decimales en una plataforma que no tiene una implementación de un tipo decimal adecuado. Lo más que podés hacer es redondear a una cierta precisión como te mostré arriba.

Cita:
Iniciado por Tachikomaia Ver Mensaje
Pero no quiero resolverlo así.
Tu ego es demasiado grande me parece....

TODAS las plataformas de desarrollo de software SERIAS tienen una implementación de un tipo numérico decimal para resolver justamente estas cuestiones, y TODOS los desarrolladores de software con un mínimo de conocimiento utilizan esa solución porque es LA SOLUCION ADECUADA para el problema en cuestión.

Pero para vos esa solución no sirve? o sea que vos solito sabes más que TODOS los diseñadores de lenguajes (serios), ingenieros y programadores del MUNDO ENTERO?

Cita:
Iniciado por Tachikomaia Ver Mensaje
¿Viste mi pregunta sobre el while?
El while (y también el for) es un constructo propio de la programación procedural. A medida que me voy metiendo más en F# (*) voy aprendiendo sobre cuestiones de programación funcional y siguiendo las buenas prácticas. Por ejemplo tratar de crear tipos inmutables y funciones puras que no tengan efectos secundarios. El while por naturaleza requiere mutabilidad, ya que usualmente vas a mutar el estado de una variable o algo por el estilo para salir del bucle. La programación funcional alienta el uso de funciones puras sobre secuencias, en lugar de "iteraciones" como las que se usan en procedural y OOP.

En definitiva: Programación funcional >>>>>>>> OOP >>>>>>>>>>>>>>> Procedural (donde ">" significa mayor que o mejor que)

(*) por cierto yo estoy aprendiendo F# y FP en este tiempo, lo cuál representa un cambio de paradigma ENORME con respecto a lo que vine haciendo durante ya casi 10 años de manera profesional (OOP), y vos no queres salir de tu "cajita" de ActionScript. Fijate....

Última edición por agleiva; 07/09/2015 a las 19:03
  #21 (permalink)  
Antiguo 07/09/2015, 21:39
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Cita:
Iniciado por agleiva Ver Mensaje
NO.

La verdad que me parece la peor idea que se te puede ocurrir.

Si tenés que realizar operaciones con números decimales usás un tipo numérico decimal. Usar punto flotante trae los problemas de redondeo (de los que ya hablamos), y hacer lo que vos planteás es innecesario, tedioso, poco práctico y muy propenso a errores, así que cuando queres manejar valores exactos usás decimal.
No he entendido, el problema que tengo con esa alternativa es que no sabría qué números debo aumentar y cuales no, no es un tema de que el código falle porque AS o las CPU fallen al contar.

Te doy un ejemplo. Digamos que tengo que hallar un número del 1 al 5 y sé que tiene hasta 2 decimales, o sea que puede ser 1 o 2.93, etc. Supongamos que ese número es la mínima defensa necesaria para que un personaje de videojuego sobreviva a un ataque -generalmente los valores son enteros, pero supongamos que no en este caso-. Si multiplico "todo" *100 entonces la búsqueda sería de un número entero, ya no decimal. Sería del 100 al 500, luego de hallarlo lo traduciría a decimal -aunque sea manualmente, es decir yo, no el programa-. Lo bueno de esto es que se puede analizar el problema sin usar decimales. El problema es que no siempre es claro qué cosas deben ser multiplicadas ni si realmente todos los casos se puede aplicar eso y funcionar bien.

Cita:
A ver si te queda claro: ESA BASURA DE ACTIONSCRIPT NO SIRVE PARA NADA.
Me sirve y lo sabes, lo que no me sirve es discutir si me sirve o no, y también lo sabes.

Cita:
No podés resolver un problema de decimales en una plataforma que no tiene una implementación de un tipo decimal adecuado. Lo más que podés hacer es redondear a una cierta precisión como te mostré arriba.
Bien, con las condiciones que plantee llegás hasta esa solución, no tenés más alternativas, ok, gracias por tu ayuda, hasta otra.

Cita:
Tu ego es demasiado grande me parece....
Igual que tu viga en el ojo.
"Ves la paja en el ojo ajeno pero no la viga en el propio".

Además ¿qué tiene que ver mi ego con querer resolver un problema con unas herremientras X? ¿qué? ¿soy muy engreído por usar herramientas limitadas? No entiendo, uso la herramienta esa porque me gusta o me resulta más cómodo, aunque vos no lo creas, pero ese es tu problema, es como que yo te diga a vos qué música escuchar. es un sin sentido si vos querés escuchar X. Yo igual, ya te lo dije, no voy a dejar de usar Flash, no jodas conque cambie, el tema no ese. No vengo a leer insultos a un lenguaje o a mi persona, vengo a ver soluciones, si las tenés bien sino callate o al menos mantené el respeto.

Cita:
Pero para vos esa solución no sirve? o sea que vos solito sabes más que TODOS los diseñadores de lenguajes (serios), ingenieros y programadores del MUNDO ENTERO?
No dije que no sirva, dije que no quiero usarla. Todo el mundo juega a un Wii o no sé qué carajo a estas alturas, yo sigo con Nes, Snes, Play1 y me divierto igual ¿tengo que hacer algo más actualizado o "mejor" porque la mayoría lo haga? No señor. Acéptalo.

Cita:
Por ejemplo tratar de crear tipos inmutables y funciones puras que no tengan efectos secundarios.
¿Qué problema podría haber en hacerlo distinto? ¿efecto secundario como cual?

Cita:
(*) por cierto yo estoy aprendiendo F# y FP en este tiempo, lo cuál representa un cambio de paradigma ENORME con respecto a lo que vine haciendo durante ya casi 10 años de manera profesional (OOP), y vos no queres salir de tu "cajita" de ActionScript. Fijate....
Bien por ti! Si con tus super conocimientos y capacidad y experiencia y versatilidad y todo lo que sea mejoras al mundo bien, pero yo voy a seguir con Flash o lo que me parezca cómodo, es mi problema ¿no lo entiendes? ¿qué vas a hacer, apuntarme con un arma para que use lo que vos queras? Madura. Habla de los temas y no de tus conocimientos, de los demás, de las plataformas, si no son el tema.

...

Ahora supongo que Malenko va a cerrar el hilo, y como si fuese mi culpa, porque me enojé, pero ¿por qué tenías que empezar a hablar de mi plataforma o de mí? Si el tema es otro. Además contigo es siempre lo mismo, sabés que no voy a cambiar de plataforma, en principio te hablé porque respondiste bien a pesar de las cositas innecesarias, pero qué qjuieres??? Pregunté cómo solucionar un problema que ocurre en varias plataformas, solucionarlo usando herramientas básicas no otras especatulares como "m" u otra plataforma ¿y por eso te enojás, te sacás, empezás a insultar la plataforma que uso y a hablar de mi ego? Mira, en un foro una persona abre un tema y pone las reglas, más o menos, "quiero esto", "busco aquello", si piden pan y no quieres dar pan no des, pero no des garrotazos en la cabeza tampoco, no respondas, te agradezco la solución que me diste, estuvo bien, pero el resto no, si el tema no te gusta no lo respondas o tené respeto, no sé, por más razón que tengas no me interesa cambiar de plataforma ¿te gustaría que alguien te diga a cada rato que la música clásica es mejor que el metal, por ejemplo? Si escuchás metal. Creo que un tal Mario Bunge dice que esa música es para alienados o que sólo se puede escuchar drogado. Yo escucho bastantes cosas, por las dudas, no estoy insultando al meta, te digo lo que me pareció que dice otro y que no te gustaría que te digan a cada rato.
¿Te gustaría que te digan a cada rato que te hagas católico, que te afeites, que te cortes el pelo, que te vistas de traje (o de algo que no te guste), etc, etc? No. Bueno, a mí tampoco me gusta toparme con insultos a Flash o a mi persona que no vienen al caso.
Ya dije que iba a ignorarte, te di oportunidades pero parece que no podés evitar que te salga mierda por la boca. Por tiempos, me fui del foro por cosas que has dicho. Si quieres insultar a Flash o AS o lo que sea deberías abrir temas, "Flash es una mierda", y puteá ahí todo lo que quieras, create un blog para insultar a AS si quieres xP Pero no me jodas a mí conque cambie o en mis temas con cosas que no vienen al caso. Si pregunto cómo hacer KO con karate no me vengas conque el karate es una mierda y que use metralletas. En definitiva yo no tengo rabia contra ti ni nada, pero logras sacarme de qusio y no entiendo, o sea, si no te gusta estar lmitado a usar lo básico ¿entonces para qué respondés mis temas que sabés que son de eso? O bueno, ta, se te escapó, o no sabías, pero lo de putear a Flash o a mí sobraba. ¿Siempre que hable contigo va a ser así? ENTENDELO: NO VOY A DEJAR DE USAR FLASH, al menos no porque vos me lo digas o porque me lo digan puteando al programa, si dejo de usarlo será porque yo mismo me harte de sus límites o me aburra de ciertas cosas de él. NO ESTÁ BIEN QUE QUIERAS OBLIGARME O QUE ME REPITAS A CADA RATO QUE ES UNA MIERDA Y QUE LO DEJE. Como si usar Flash fuese un delito o algo por el estilo, por favor. Así que, no respondas mis temas si es para putearme o a Flash/AS.
Si querés putear a Flash/AS, abre tu un tema, o create un blog, haz videos de youtube o lo que sea. Virus no, please. ¿No hay algún político malvado en tu país o algo por el estilo a quien debas putear y a su política más de lo que me puteas a mí y a Flash? Bueno, ve a por él, dejame tranquilo.
  #22 (permalink)  
Antiguo 07/09/2015, 21:47
(Desactivado)
 
Fecha de Ingreso: enero-2015
Mensajes: 393
Antigüedad: 9 años, 10 meses
Puntos: 52
Respuesta: Problema con decimales.

AJAJAJ buscate una novia, capo.

O un novio, o lo que prefieras...

Nos re vimos.

Por cierto: decis "flash me sirve" - jajaja.. si, te sirve *tanto* que hace 5 años que estas en este foro y seguís dando vueltas en lo mismo y nunca hiciste nada, ni aprendiste nada útil (al menos no relacionado a la programación)

Chau, que te vaya bien. Seguí con tu bici playera... Nos vemo en disney.

Última edición por agleiva; 07/09/2015 a las 21:53
  #23 (permalink)  
Antiguo 08/09/2015, 11:51
Tachikomaia
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Problema con decimales.

Con esto está solucionado:
Código a:
Ver original
  1. Act = 0;
  2. ActDec = 1;
  3. do {
  4.     Precision = Math.round(Math.pow(10, ActDec));
  5.     Act = (Act*Precision+1)/Precision;
  6.     trace (Act);
  7. } while (Act<0.9);
  8. if (Act>0.9) {
  9.     trace ("Sí");
  10. }
Puede que surjan problemas en otros casos pero eso tendré que verlo.

Es básicamente lo mismo que postee antes pero redondeando el cálculo de 10 elevado a ActDec, porque eso Flash lo calcula mal, por lo visto. Cuando usaba "Precision" para multiplicar o dividir, los resultados eran decimales larguísimos. Es curioso sí que en esos casos aparecen como tales y en otros no aunque también lo sean. Pero el caso es que si dividía y multiplicaba con 10 no había problema. Bueno, redondear el cálculo de Precision parece haber solucionado el problema, como si hacer 10 a la 1 resultara 9.9999999 o quién sabe qué.
  #24 (permalink)  
Antiguo 08/09/2015, 13:04
(Desactivado)
 
Fecha de Ingreso: marzo-2012
Mensajes: 366
Antigüedad: 12 años, 7 meses
Puntos: 31
Respuesta: Problema con decimales.

Cita:
Iniciado por Tachikomaia Ver Mensaje

Parece lo mismo, pero me es complicado pensar lo tuyo, a ver:
ConvertirADecimal(ConvertirAEntero(NúmeroDecimal * 10^n))/10^n
En efecto, la fórmula es parecida a la tuya. Pero no exactamente igual.

La verdadera magia pasa al convertir el número decimal a entero. Al hacerlo eliminas todos los decimales indeseados. Si quieres solo un decimal, pero tienes el número 4,9999999, y lo quieres dejar a 4,9 y no tener ninguna duda con la precisión de que si es realmente 4,9 o 5 o 4,99 o 4,91... todas esas dudas te las quitas al hacer esas transformaciones. Porque ese 4,9 pasa a ser 49 exacto, sin decimal ninguno, sin duda alguna de si es 49 o 49.999 porque eso es imposible que sea, ya que tiene que ser el número entero y no caben decimales.

Y como un número entero no puede tener decimales no puede tener tampoco ese problema que tienes. Y una vez eliminado ese problema de que si es realmente 0.4 o 0.49 porque ya estás seguro de que lo que tienes son los dígitos exactos que quieres... pues lo devuelves a decimal y lo divides. Y al hacerlo ya ese decimal no coje más decimales por sorpresa. El 0.49 no se convierte en 0.49999 ni en 0.48999 ni nada parecido. 49 exactos / 100=0.49 y punto.

Desconozco si todos los lenguajes distinguen entre esos tipos de datos, y pueden definir enteros o decimales y restringir de esa manera si tienen decimales o no. Java si tiene esta distinción entre esos 2 tipos de datos. Pero no te se decir sobre ningún otro lenguaje más.

Etiquetas: programa
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 14:26.