¿Hay una biblioteca que convertirá un Doble en una Cadena con el número entero, seguido de una fracción?Formato Doble como Fracción
Por ejemplo
1.125 = 1 1/8
Sólo estoy buscando para las fracciones a un 64o de una pulgada.
¿Hay una biblioteca que convertirá un Doble en una Cadena con el número entero, seguido de una fracción?Formato Doble como Fracción
Por ejemplo
1.125 = 1 1/8
Sólo estoy buscando para las fracciones a un 64o de una pulgada.
Un problema con el que pueden toparse es que no todos los valores fraccionarios se pueden representar por dobles. Incluso algunos valores que parecen simples, como 0.1. Ahora con el algoritmo de pseudocódigo. Probablemente sea mejor que determine la cantidad de 64ths de una pulgada, pero dividiendo la porción decimal por 0.015625. Después de eso, puedes reducir tu fracción al mínimo común denominador. Sin embargo, dado que indica las pulgadas, es posible que no desee utilizar el denominador común más pequeño, sino solo los valores para los que usualmente se representan las pulgadas, 2,4,8,16,32,64.
Sin embargo, una cosa para señalar es que, dado que está usando pulgadas, si los valores son todas fracciones de una pulgada, con un denominador de 2,4,8,16,32,64, entonces el valor nunca debería contienen errores de punto flotante, porque el denominador siempre tiene una potencia de 2. Sin embargo, si tu conjunto de datos tuviera un valor de .1 pulgada allí, entonces comenzarías a tener problemas.
No estoy de acuerdo, basándome en el hecho de que Milhous quiere cubrir pulgadas hasta 1/64 " Supongamos que el programa exige una precisión de 1/64" en todo momento, que debería ocupar 6 bits de la mantisa. En un carro, hay 24-6 = 18, lo que (si mis cálculos son correctos), debería significar que tiene un rango de +/- 262144 + 63/64 "
Eso podría ser suficiente precisión en el flotador para convertir correctamente en la facción sin pérdida.
Y puesto que la mayoría de las personas que trabajan en pulgadas utiliza denominador de potencias de 2, que debería estar bien.
Pero volviendo a la pregunta original, no sé ninguna biblioteca que haría eso.
La función para esto en una variante C llamada LPC sigue. Algunas notas:
string strfrac(float frac) {
int main = to_int(frac + frac/1000000.0);
string out = to_string(main);
float rem = frac - to_float(main);
string rep;
if(rem > 0 && (to_int(rep = to_string(rem)) || member(rep, 'e') == Null)) {
int array primes = ({ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 });
string base;
int exp;
int num;
int div;
if(sscanf(rep, "%se%d", base, exp) == 2) {
num = to_int(replace(base, ".", ""));
div = to_int(pow(10, abs(exp)));
} else {
rep = rep[2..];
num = to_int(rep);
div = to_int(pow(10, strlen(rep)));
}
foreach(int prime : primes) {
if(prime > num)
break;
while((num/prime) * prime == num && (div/prime) * prime == div) {
num /= prime;
div /= prime;
}
}
out += " " + num + "/" + div;
}
return out;
}
Su problema es bastante simple, ya que está asegurado el denominador siempre dividirá 64. en C# (que alguien se sienta libre de traducir una versión de Java):
string ToMixedFraction(decimal x)
{
int whole = (int) x;
int denominator = 64;
int numerator = (int)((x - whole) * denominator);
if (numerator == 0)
{
return whole.ToString();
}
while (numerator % 2 == 0) // simplify fraction
{
numerator /= 2;
denominator /=2;
}
return string.Format("{0} {1}/{2}", whole, numerator, denominator);
}
Bono: Código Golf
public static string ToMixedFraction(decimal x) {
int w = (int)x,
n = (int)(x * 64) % 64,
a = n & -n;
return w + (n == 0 ? "" : " " + n/a + "/" + 64/a);
}
Mi código es así.
public static int gcd(int a, int b)
{
if (b == 0)
return a;
else
return gcd(b, a % b);
}
public static String doubleToStringFraction(Double d)
{
StringBuffer result = new StringBuffer(" " + ((int) Math.floor(d)));
int whole = (int) ((d - Math.floor(d)) * 10000);
int gcd = gcd(whole, 10000);
result.append(" " + (whole/gcd) + "/" + 10000/gcd + " ");
return result.toString();
}
Para resolver este problema (en uno de mis proyectos), tomé los siguientes pasos:
¿Qué tal org.apache.commons.math? Tienen una clase Fraction que toma un doble.
http://commons.apache.org/math/api-1.2/org/apache/commons/math/fraction/Fraction.html
Usted debe ser capaz de extender y darle funcionalidad para la 64a. Y también puede agregar un toString que imprimirá fácilmente la parte del número entero de la fracción por usted.
Fracción (valor doble, Int maxDenominator) Crear una fracción dado el valor doble y máximo denominador.
Le doy un vistazo, gracias. – Milhous
Como han salido muchas otras, las fracciones de 64 pueden ser representadas con precisión por IEEE-floats. Esto significa que también podemos convertir a una fracción moviendo y enmascarando bits.
Este no es el lugar para explicar todos los detalles de las representaciones de punto flotante, consulte wikipedia para obtener más información.
En pocas palabras: un número de punto flotante se almacena como (signo) (exp) (frac) donde signo es 1 bit, exp es 11 bits y frac es la parte de fracción (después de 1.) y es 52 bits. Esto se enterpreted como el número:
(sign == 1 ? -1 : 1) * 1.(frac) * 2^(exp-1023)
Por lo tanto, podemos obtener la 64 moviendo el punto de accoring al exponente y el enmascaramiento de los 6 bits después de la coma. En Java:
private static final long MANTISSA_FRAC_BITMAP = 0xfffffffffffffl;
private static final long MANTISSA_IMPLICIT_PREFIX = 0x10000000000000l;
private static final long DENOM_BITMAP = 0x3f; // 1/64
private static final long DENOM_LEN = 6;
private static final int FRAC_LEN = 52;
public String floatAsFrac64(double d) {
long bitmap = Double.doubleToLongBits(d);
long mantissa = bitmap & MANTISSA_FRAC_BITMAP | MANTISSA_IMPLICIT_PREFIX;
long exponent = ((bitmap >> FRAC_LEN) & 0x7ff) - 1023;
boolean negative = (bitmap & (1l << 63)) > 0;
// algorithm:
// d is stored as SE(11)F(52), implicit "1." before F
// move point to the right <exponent> bits to the right:
if(exponent > FRAC_LEN) System.out.println("warning: loosing precision, too high exponent");
int pointPlace = FRAC_LEN-(int)exponent;
// get the whole part as the number left of the point:
long whole = mantissa >> pointPlace;
// get the frac part as the 6 first bits right of the point:
long frac = (mantissa >> (pointPlace-DENOM_LEN)) & DENOM_BITMAP;
// if the last operation shifted 1s out to the right, we lost precision, check with
// if any of these bits are set:
if((mantissa & ((MANTISSA_FRAC_BITMAP | MANTISSA_IMPLICIT_PREFIX) >> (pointPlace - DENOM_LEN))) > 0) {
System.out.println("warning: precision of input is smaller than 1/64");
}
if(frac == 0) return String.format("%d", whole);
int denom = 64;
// test last bit, divide nom and demon by 1 if not 1
while((frac & 1) == 0) {
frac = frac >> 1;
denom = denom >> 1;
}
return String.format("%d %d/%d", whole, frac, denom);
}
(este código, probablemente, puede hacerse más corto, pero la lectura de bit-flipping-código como esto es suficiente ya que es difícil ...)
escribí esto para mi proyecto espero podría ser útil:
//How to "Convert" double to fraction("a/b") - [email protected]
private boolean isInt(double number){
if(number%2==0 ||(number+1)%2==0){
return true;
}
return false;
}
private String doubleToFraction(double doub){
//we get the whole part
int whole = (int)doub;
//we get the rest
double rest = doub - (double)whole;
int numerator=1,denominator=1;
//if the whole part of the number is greater than 0
//we'll try to transform the rest of the number to an Integer
//by multiplying the number until it become an integer
if(whole >=1){
for(int i = 2; ; i++){
/*when we find the "Integer" number(it'll be the numerator)
* we also found the denominator(i,which is the number that transforms the number to integer)
* For example if we have the number = 2.5 when it is multiplied by 2
* now it's 5 and it's integer, now we have the numerator(the number (2.5)*i(2) = 5)
* and the denominator i = 2
*/
if(isInt(rest*(double)i)){
numerator = (int)(rest*(double)i);
denominator = i;
break;
}
if(i>10000){
//if i is greater than 10000 it's posible that the number is irrational
//and it can't be represented as a fractional number
return doub+"";
}
}
//if we have the number 3.5 the whole part is 3 then we have the rest represented in fraction 0.5 = 1/2
//so we have a mixed fraction 3+1/2 = 7/2
numerator = (whole*denominator)+numerator;
}else{
//If not we'll try to transform the original number to an integer
//with the same process
for(int i = 2; ; i++){
if(isInt(doub*(double)i)){
numerator = (int)(doub*(double)i);
denominator = i;
break;
}
if(i>10000){
return doub+"";
}
}
}
return numerator+"/"+denominator;
}
Creo simplemente la biblioteca Fraction.
La biblioteca está disponible aquí: https://github.com/adamjak/Fractions
Ejemplo:
String s = "1.125";
Fraction f1 = Fraction.tryParse(s);
f1.toString(); // return 9/8
Double d = 2.58;
Fraction f2 = Fraction.createFraction(d);
f2.divide(f1).toString() // return 172/75 (2.29)
Los datos que entra es buena (siempre en 64ths de una pulgada) – Milhous