11/09/2009, 08:32
|
| | | Fecha de Ingreso: septiembre-2007 Ubicación: Guatemala
Mensajes: 130
Antigüedad: 17 años, 2 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.
__________________ 死は永遠の一歩だ |