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

Convertir Decimal a Fracción

Estas en el tema de Convertir Decimal a Fracción en el foro de .NET en Foros del Web. Hola como están fijense que tengo una función que me convierte decimales a fracción, la cosa es que no me lo convierte bien, dado que ...
  #1 (permalink)  
Antiguo 09/09/2009, 15:41
Avatar de cadesa  
Fecha de Ingreso: septiembre-2007
Ubicación: Guatemala
Mensajes: 130
Antigüedad: 16 años, 7 meses
Puntos: 0
Busqueda Convertir Decimal a Fracción

Hola como están fijense que tengo una función que me convierte decimales a fracción, la cosa es que no me lo convierte bien, dado que si tengo 1.33333 la conversión me muestra 1 333/1000 y el número correcto es 4/3 por lo cual yo quisieran que me dieran su opinion y me dijeran en como puedo mejorar el código para que me despliegue los datos correctamente.

Código Código de Fracción VB.NET:
Ver original
  1. Public Function ConvFraccion(ByVal Numero As Decimal) As String
  2.         Dim Numerador, Denominador, Entero As Integer
  3.         Dim Simplificar As Boolean
  4.         Entero = Decimal.Truncate(Numero)
  5.         Numerador = (Numero - Entero) * 100000
  6.         Denominador = 100000
  7.         If Numero - Entero = 0 Then
  8.             ConvFraccion = CStr(Entero)
  9.         Else
  10.             Simplificar = True
  11.             Do While Simplificar
  12.                 If Numerador Mod 2 = 0 And Denominador Mod 2 = 0 Then
  13.                     Numerador = Numerador / 2
  14.                     Denominador = Denominador / 2
  15.                 Else
  16.                     If Numerador Mod 3 = 0 And Denominador Mod 3 = 0 Then
  17.                         Numerador = Numerador / 3
  18.                         Denominador = Denominador / 3
  19.                     Else
  20.                         If Numerador Mod 5 = 0 And Denominador Mod 5 = 0 Then
  21.                             Numerador = Numerador / 5
  22.                             Denominador = Denominador / 5
  23.                         Else
  24.                             If Numerador Mod 7 = 0 And Denominador Mod 7 = 0 Then
  25.                                 Numerador = Numerador / 7
  26.                                 Denominador = Denominador / 7
  27.                             Else
  28.                                 If Numerador Mod 13 = 0 And Denominador Mod 13 = 0 Then
  29.                                     Numerador = Numerador / 13
  30.                                     Denominador = Denominador / 13
  31.                                 Else
  32.                                     Simplificar = False
  33.                                 End If
  34.                             End If
  35.                         End If
  36.                     End If
  37.                 End If
  38.             Loop
  39.             If Entero <> 0 Then
  40.                 ConvFraccion = CStr(Entero) + " " + CStr(Numerador) + "/" + CStr(Denominador)
  41.             Else
  42.                 ConvFraccion = CStr(Numerador) + "/" + CStr(Denominador)
  43.             End If
  44.         End If
  45.     End Function
__________________
死は永遠の一歩だ
  #2 (permalink)  
Antiguo 10/09/2009, 10:30
Avatar de StephenQ  
Fecha de Ingreso: marzo-2007
Mensajes: 114
Antigüedad: 17 años, 1 mes
Puntos: 2
Respuesta: Convertir Decimal a Fracción

Hola Amigo mira esto http://www.geocities.com/oosterwal/c...onversion.html
__________________
StephenQ
  #3 (permalink)  
Antiguo 11/09/2009, 08:32
Avatar de cadesa  
Fecha de Ingreso: septiembre-2007
Ubicación: Guatemala
Mensajes: 130
Antigüedad: 16 años, 7 meses
Puntos: 0
Respuesta: Convertir Decimal a Fracción

Gracias pero fijate que no da bien los valores, ya lo revise.

Luego de poner el tema me puse a trabajar para poder dar los valores mas exactos aunque no me quedo bien bien del todo puedo decirles que si esta lo mas cercano a la realidad, por lo que voy a colocar el código aquí.


''' <summary>
''' Contiene metodos para convertir decimales a fracción así metodos par convertir
''' fracción a decimal.
''' </summary>
''' <remarks></remarks>
Public Class Convierte_Fraccion

Private num, den As Integer

''' <summary>
''' Devuelve la fracción de un número decimal.
''' </summary>
''' <param name="numero">Número decimal a convertir a fracción.</param>
''' <returns>String.</returns>
''' <remarks></remarks>
Public Function convertidor(ByVal numero As Decimal) As String
'Variables para obtener la fracción
Dim entero, numerador, denominador, total_decimales As Integer
'Valor que tiene la cantidad decimal
Dim decimales As Double = numero - Fix(numero)
entero = Decimal.Truncate(numero)

'Valido si tiene decimales
If decimales > 0 Then
'Asigno el número de "0" por el cual se completará el "1" para multiplicar.
'esto por ejemplo si se tiene 2.5 entonces la cantidad es 10.
total_decimales = multiplicador_fraccion(decimales)

'Valido si es o no periodico la cantidad de decimales.
If es_periodico(decimales) Then
'Realizo la conversión de los decimales a fracción, todavía no agrego el entero.
convertidor = simplificador_fraccion(False, 0, 0, decimales)
Else
'Realizo el calculo que se tendrá para el calculo de lo numerado y denominador solo
'si este no es periodico.
numerador = decimales * total_decimales
denominador = total_decimales

'Convierto la parte decimal a fracción, y le envio el númerador y denominador.
convertidor = simplificador_fraccion(True, numerador, denominador, 0)
End If

'Valido si el entero es uno para darle la conversión mas exacta.
'Aquí es donde no se como validar en ciertos casos.
If entero = 1 Then
'Calculo el valor de la fracción impropia.
numerador = ((entero * den) + num)
denominador = den

'Valido si el numerador es mayor a denominador, y si lo es crea la fracción impropia y
'ya no llevo entero, sino no hace nada.
If numerador > denominador Then
convertidor = CStr(numerador) + "/" + CStr(denominador)
entero = 0
End If

ElseIf entero > 1 Then
'Asigno la fracción con el entero para darle valor mas exacto.
convertidor = CStr(entero) + " " + convertidor
End If
Else
'Si no tiene decimal devuelvo un vacío.
convertidor = ""
End If
End Function

''' <summary>
''' Obtiene la cantidad por la cual se multiplicarán los numeradores y denominadores.
''' </summary>
''' <param name="_no_decimal">Valor decimal del número.</param>
''' <returns>Entero</returns>
''' <remarks></remarks>
Private Function multiplicador_fraccion(ByVal _no_decimal As Double) As Integer
'Obtengo la parte del punto
Dim dec As String = obtiene_decimal(_no_decimal)
'Declaro y Asigno el "1" que se completará con "0" para volver el valor decimal a fracción.
Dim primario As Integer = 1
'Declaro y asigno la variable que llevará "0" a concatenar.
Dim concatenador As String = "0"

'Valido si el largo de la cadena de decimales es mayor a 1
'para completar con 0's la información.
If Len(dec) > 1 Then
'Lleno de 0's la variable tanto como tenga la cadena.
For i As Integer = 0 To Len(dec) - 1
concatenador += "0"
Next
End If

'Concateno el multiplicador y lo asigno a la función, y lo envío como un entero.
multiplicador_fraccion = CInt(CStr(primario) + concatenador)
End Function
''' <summary>
''' Simplifica la fracción a su mínima expresión.
''' </summary>
''' <param name="simplificar">Bandera que validará si se simplifica o no la fracción.</param>
''' <param name="numerador">Numerador de la fracción.</param>
''' <param name="denominador">Denominador de la fracción.</param>
''' <param name="decimales">Valor decimal para sacar la fracción por si este tiene un valor periodico.</param>
''' <returns>String</returns>
''' <remarks></remarks>
Private Function simplificador_fraccion(ByVal simplificar As Boolean, ByVal numerador As Integer, ByVal denominador As Integer, ByVal decimales As Double) As String
'Valido si se tiene que reducir a su menor expresion o no los decimales.
Select Case simplificar
Case True
'Se realiza la simplificación a su menor expresión y se asignan los valores
'de numerador y denominador simplificados a las variables globales.
Do While simplificar
If numerador Mod 2 = 0 And denominador Mod 2 = 0 Then
numerador = numerador / 2
denominador = denominador / 2
Else
If numerador Mod 3 = 0 And denominador Mod 3 = 0 Then
numerador = numerador / 3
denominador = denominador / 3
Else
If numerador Mod 5 = 0 And denominador Mod 5 = 0 Then
numerador = numerador / 5
denominador = denominador / 5
Else
If numerador Mod 7 = 0 And denominador Mod 7 = 0 Then
numerador = numerador / 7
denominador = denominador / 7
Else
If numerador Mod 13 = 0 And denominador Mod 13 = 0 Then
numerador = numerador / 13
denominador = denominador / 13
Else
simplificar = False
num = numerador
den = denominador
End If
End If
End If
End If
End If
Loop

Case False
'Se obtiene el valor para el numerador y el denominador cuando
'este la parte de fracción es periodico y se asignan a las variables
'globales.
Dim valor_periodico As Integer = CInt(Mid(obtiene_decimal(decimales), 1, 1))
Dim valor_real As Decimal = decimales * valor_periodico
numerador = Decimal.Round(valor_real, 0)
denominador = valor_periodico

num = numerador
den = denominador
End Select

'Retorno la parte fraccionaria.
simplificador_fraccion = CStr(numerador) + "/" + CStr(denominador)
End Function
''' <summary>
''' Valida si es o no periodico un número.
''' </summary>
''' <param name="_no_decimal">Número a validar.</param>
''' <returns>Boolean</returns>
''' <remarks></remarks>
Private Function es_periodico(ByVal _no_decimal As Double) As Boolean
'Obtengo el valor decimal del número.
Dim dec As String = obtiene_decimal(_no_decimal)
'Obtengo el primer valor que se tiene en la cadena de decimales.
Dim caracter As String = dec.Substring(0, 1)
'Declaro las variables contadoras.
Dim i As Integer, num As Integer

'Recorro la cadena de decimales para verificar si es o no periodico el número.
For i = 1 To Len(dec)
'Valido de uno en uno cada decimal con el primer caracter para ver si es
'o no periodico, si es sumo 1 a la variable contadora.
If Mid(dec, i, 1) = caracter Then
num = num + 1
End If
Next

'Valido si la cadena de decimales es igual a la variable contadora del periodico
'si es igual y si la cadena es mayor a 1 (excluye 0.5,0.6, etc.) entonces
'indico que es periodico, sino es falso.
If Len(dec) = num And Len(dec) > 1 Then
es_periodico = True
Else
es_periodico = False
End If
End Function
''' <summary>
''' Devuelve la parte decimal de un número.
''' </summary>
''' <param name="_no_decimal">Número a reducir.</param>
''' <returns>String</returns>
''' <remarks></remarks>
Private Function obtiene_decimal(ByVal _no_decimal As Double) As String
'Obtengo el largo de la cadena con el punto para verificar la parte entera.
Dim punto As String = _no_decimal.ToString.LastIndexOf(".") + 1
'Resto la cadena total al número que obtuve anteriormente, para saber cuantos
'decimales tomar.
Dim cant_decimal As Integer = _no_decimal.ToString.Length - punto.ToString
'Obtengo únicamente la parte decimal, excluyendo su parte entera y el punto.
Dim dec As String = _no_decimal.ToString.Substring(punto, cant_decimal)

obtiene_decimal = dec
End Function

End Class



Aunque no estoy muy convencido del todo, si ustedes puede ayudarme para hacerlo mas eficiente mucho que mejor pero aqui les pongo parte de la solución final.
__________________
死は永遠の一歩だ
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 09:16.