是否有一个库可以将Double转换为具有整数的String,后跟一个分数?
例如
1.125 = 1 1/8
我只是寻找到64英寸的分数。
答案 0 :(得分:10)
你的问题非常简单,因为你确信分母总是会在C#中划分64.(有人随意翻译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);
}
奖金:Code 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);
}
答案 1 :(得分:5)
您可能遇到的一个问题是并非所有小数值都可以用双精度表示。甚至一些看似简单的值,如0.1。现在开始使用伪代码算法。您可能最好确定64英寸的数字,但将小数部分除以0.015625。之后,您可以将分数降低到最小公分母。但是,由于你说的是英寸,你可能不想使用最小的公分母,而只是使用通常表示英寸的值,2,4,8,16,32,64。
有一点要指出的是,因为你使用的是英寸,如果这些值都是一英寸的合适分数,分母为2,4,8,16,32,64,则该值不应包含浮点错误,因为分母总是2的幂。但是如果你的数据集的值为.1英寸,那么你就会遇到问题。
答案 2 :(得分:4)
org.apache.commons.math怎么样?他们有一个Fraction类需要加倍。
http://commons.apache.org/math/api-1.2/org/apache/commons/math/fraction/Fraction.html
您应该能够扩展它并为第64个功能提供功能。而且你还可以添加一个toString,它可以轻松地为你打印出整数部分。
分数(double value,int maxDenominator)创建一个分数 给出双倍值和最大值 分母。
答案 3 :(得分:3)
我不一定同意,基于Milhous想要覆盖1/64英寸的事实 假设程序始终要求1/64“精度,那应该占用尾数的6位。在浮点数中,有24-6 = 18,(如果我的数学是正确的),应该意味着他有一个范围+/- 262144 + 63/64“
浮点数可能足够精确,可以毫无损失地正确转换为阵营。
由于大多数使用英寸的人使用2的幂的分母,所以应该没问题。
但回到最初的问题,我不知道会有任何图书馆会这样做。
答案 4 :(得分:1)
以下称为LPC的C变体的功能如下所示。一些说明:
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;
}
答案 5 :(得分:1)
我为我的项目写了这个,我希望它可能有用:
//How to "Convert" double to fraction("a/b") - kevinlopez@unitec.edu
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;
}
答案 6 :(得分:0)
我的代码看起来像这样。
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();
}
答案 7 :(得分:0)
正如其他几个人所说的那样,64分的分数可以由IEEE浮点数精确地表示。这意味着我们也可以通过移动和屏蔽位来转换为分数。
这不是解释浮点表示的所有细节的地方,详情请参阅wikipedia。
简要说明:浮点数存储为(符号)(exp)(frac),其中符号为1位,exp为11位,frac为小数部分(1之后),为52位。这是作为数字输入的:
(sign == 1 ? -1 : 1) * 1.(frac) * 2^(exp-1023)
因此,我们可以通过移动符合指数的点并在该点之后屏蔽6位来获得第64位。在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);
}
(这段代码可能会缩短,但是阅读像这样的位翻码代码很难,因为它......)
答案 8 :(得分:0)
我只创建了Fraction库。
图书馆可在此处找到:https://github.com/adamjak/Fractions
示例:
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)
答案 9 :(得分:-1)
为了解决这个问题(在我的一个项目中),我采取了以下步骤: