[ Foro de Pascal ]

Multiplo de 0.25

16-Apr-2015 16:39
Mario Martin Ortiz
12 Respuestas

Necesito un programa que dado un numero real, me diga si es multiplo o no de 0.25, ¿alguien me da alguna idea de como hacerlo?


17-Apr-2015 17:38
Nacho Cabanes (+83)

Tendrás que dividir ese número real entre 0.25 y ver si el resto de la división es cero (realmente, si es menor que cierto número arbitrario, como 0.00001).


17-Apr-2015 17:45
Mario Martin Ortiz

Lo unico que si el numero es de tipo real, no puedo hacer el resto (ya que no existe)  sin embargo, se me ha ocurrido una opcion esta mañana: si  el (numero x4) = (numero x4) truncado, entonces ya me asegura que es multiplo. Muchas gracias aun asi. Un saludo


17-Apr-2015 19:08
Luis Torres (+18)

Eso no te garantiza que todo número que introduzca el usuario sea múltiplo de 0.25. Solo sirve para números enteros. Supongamos que se ingrese 1.25, el programa responderá que no es múltiplo de 0.25, pero sí lo es.

Saludos.


17-Apr-2015 19:55
Mario Martin Ortiz

A ver, 1,25*4=5, por lo tanto, 5 sera igual a 5 truncado, el programa funciona perfectamente, lo acabo de probar.
gracias


17-Apr-2015 23:08
Luis Torres (+18)

Disculpa, es que no interpreté la "x" como signo de multiplicación, pensaba que así se llamaba la variable.

Saludos.


17-Apr-2015 23:14
Nacho Cabanes (+83)

Una cosa es que, por no ser números enteros, no puedas aplicar directamente la operación "mod" del lenguaje Pascal, y otra cosa distinta es que no se pueda calcular el resto de una división.

Si quieres usar "mod", puedes multiplicar tanto dividendo como divisor por un número, como ya has hecho, pero mejor si es un número grande que uno tan pequeño como 4, para que los errores por redondeo sean tan pequeños como sea posible (prueba 1. 25, que sí es divisible, pero también 1.30, que no lo es, y asegúrate de que ambas  respuestas que obtienes son  correctas).

La otra alternativa es calcular tú el resto de la división, sin usar "mod".  Si  piensas cómo lo harías en papel, verás que sólo necesitas una división, una multiplicación y una resta.


19-Apr-2015 19:01
Luis Torres (+18)

Me gusta más el planteamiento que hizo el profesor Nacho Cabanes, porque se presta más a un proceso que se pueda llevar a cabo mediante la programación, es decir, el hacer que un conjunto de pasos que normalmente tiene que llevar a cabo a mano una persona pueda transformarse en un conjunto de instrucciones de un programa de computación. La solución de  Mario Martin Ortiz es válida, pero tiende a ser una solución más que todo matemática, un especialista en esa área obtuvo esa idea y me la presentó, lo que me simplificó el problema; pero no a todos se nos ocurren esas ideas tan maravillosas que nos ahorran dolores de cabeza.

Por mi parte, le hice caso al profesor Nacho Cabanes, tomé una hoja de papel, hice varias divisiones y tomé nota de cada uno de los pasos a seguir para obtener el resto de esas divisiones. El resto se obtiene multiplicando el divisor por la division y lo que obtenemos debemos restárselo al dividendo. O sea, así resto = dividendo - (division * DIVISOR); si el resto es cero entonces hay divisibilidad exacta, caso contrario, no la habría. Tomando en cuenta todo esto, elaboré el siguiente código, espero que si tengo algún error me lo hagan saber:


program Divisibilidad;

const DIVISOR = 0.25;

var
  dividendo, division, resto: real;
  
BEGIN
  write('Introduzca el numero real: '); readln(dividendo);
  division:= dividendo/DIVISOR;
  division:= trunc(division);
  resto:= dividendo - (division * DIVISOR);

  if (resto = 0) then
    writeln('El numero introducido es divisible por ',DIVISOR:0:2)
  else
    writeln('El numero introducido no es divisible por ',DIVISOR:0:2);  
  readln;
END. 


Saludos.


19-Apr-2015 20:46
Mario Martin Ortiz

Muchas gracias a todos por las aportaciones, la verdad es que me han sido de gran utilidad, tener distintos puntos de enfoque a una misma pregunta, aunque finalmente me quedare con la opcion que yo pense. Un saludo


20-Apr-2015 06:22
Luis Torres (+18)

Siempre he escuchado que no debo utilizar comparaciones de igualdad en las condiciones de un ciclo o sentencia if. La verdad es que no entendí mucho lo que me explicó sobre usar el valor absoluto y compararlo con un cierto valor pequeño. ¿Cómo quedaría el if de mi código haciendo esos cambios?

Saludos y gracias por su explicación.


20-Apr-2015 09:51
Nacho Cabanes (+83)

A Mario: insisto, lleva cuidado con los errores de redondeo. Si el usuario introduce 1.30, que no es divisible entre 1.25, al truncar obtendrás 5 en ambos casos, y tu programa responderá que sí es divisible (no veo tu fuente, pero si tu planteamiento es el que has comentado de multiplicar por 4, puedes tener ese tipo de errores).

A Luis: el problema se da sólo con los números reales, que se almacenan con precisión garantizada sólo hasta cierta cantidad de cifras. Con los enteros no existe ese riesgo. El programa podría quedar así:


program Divisibilidad;
 
const DIVISOR = 0.25;
 
var
  dividendo, division, resto: real;
 
BEGIN
  write('Introduzca el numero real: '); readln(dividendo);
  division:= dividendo/DIVISOR;
  division:= trunc(division);
  resto:= dividendo - (division * DIVISOR);
 
  if (abs(resto) < 0.001) then
    writeln('El numero introducido es divisible por ',DIVISOR:0:2)
  else
    writeln('El numero introducido no es divisible por ',DIVISOR:0:2);  
  readln;
END. 


 


20-Apr-2015 17:55
Luis Torres (+18)

Ok, pero si resto vale 0.0005 sería menor que 0.001, y resto no es cero, por lo tanto el dividendo no sería divisible exactamente.


En cuanto a lo que escribió a Mario Martin Ortiz, si el usuario introduce 1.30. Tendríamos las siguientes operaciones:

1.30 * 4 = 5.2
ahora, el truncado de 5.2 es 5.0
entonces 5.2 es diferente de 5.0;
por lo tanto 1.30 no es divisible exactamente por 0.25

Saludos.


25-Apr-2015 10:34
Nacho Cabanes (+83)

Pero si el resto es 0.0005, normalmente ya entramos en un rango que se debe a errores de redondeo. (según el tipo de datos, puede ocurrir que tengas apenas 6-7 cifras de precisión).

Tienes razón con lo del 1.30. Él escribió " si  el (numero x4) = (numero x4) truncado" y yo había interpretado " si  el (numero x4) truncado = (numero buscado x4) truncado" y en ese caso 1.30x4 = 5.20, que truncado es 5, al igual que 1.25, que sí es divisible.

En cualquier caso, sigue siendo peligroso usar un símbolo de igualdad para comprobar el resultado de una división entre números reales, por posibles errores de redondeo. En este caso concreto, es un poco grave de lo que podría ser, porque la parte fraccionaria de un número real (al igual que la parte entera) se suele guardar como una potencia de 2, y 0.25 es 1/4, por lo que en un ordenador convencional con un compilador habitual, que usen números en coma flotante guardados en formato binario, ese dato se almacenaría sin pérdida de precisión. Pero lo importante es el concepto, porque el comparar igualdad entre números reales da lugar a errores de ejecución muy difíciles de detectar, porque las dos partes de la igualdad pueden parecer idénticas a ojos de un humano pero no almacenarse exactamente igual.






(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)