我需要使用以下格式将双精度值(厘米)转换为分数值:3 1/64(英寸)。在阅读了很多关于这个并找到转换成分数的算法后,我认为它们不适合我需要的东西,因为我的分数应该是这些格式:?/2、?/4、?/8、?/16, ?/32, ?/64。我见过这样的转换表:table。我认为我最好的解决方案是创建一个键值列表,其中包含表中的所有值,并为每个数字找到列表中的最佳近似值。
例如:3.21 厘米。= 1.26378 英寸 = 1 英寸 + 0.26378。因此,根据链接的表格,0.26378 = 17/64。最终结果应该是 1 17/64 英寸。
所以我的问题是:
有一个包含表中值的列表并找到最接近的值以给出分数是一个好主意,还是最好为此创建一个算法?
如果可以用这些值创建一个列表,我如何在我的列表中找到给定数字的最接近的值?
我建议使用简单的数学而不是表格
private static string ToFraction64(double value) {
// denominator is fixed
int denominator = 64;
// integer part, can be signed: 1, 0, -3,...
int integer = (int) value;
// numerator: always unsigned (the sign belongs to the integer part)
// + 0.5 - rounding, nearest one: 37.9 / 64 -> 38 / 64; 38.01 / 64 -> 38 / 64
int numerator = (int) ((Math.Abs(value) - Math.Abs(integer)) * denominator + 0.5);
// some fractions, e.g. 24 / 64 can be simplified:
// both numerator and denominator can be divided by the same number
// since 64 = 2 ** 6 we can try 2 powers only
// 24/64 -> 12/32 -> 6/16 -> 3/8
// In general case (arbitrary denominator) use gcd (Greatest Common Divisor):
// double factor = gcd(denominator, numerator);
// denominator /= factor;
// numerator /= factor;
while ((numerator % 2 == 0) && (denominator % 2 == 0)) {
numerator /= 2;
denominator /= 2;
}
// The longest part is formatting out
// if we have an actual, not degenerated fraction (not, say, 4 0/1)
if (denominator > 1)
if (integer != 0) // all three: integer + numerator + denominator
return string.Format("{0} {1}/{2}", integer, numerator, denominator);
else if (value < 0) // negative numerator/denominator, e.g. -1/4
return string.Format("-{0}/{1}", numerator, denominator);
else // positive numerator/denominator, e.g. 3/8
return string.Format("{0}/{1}", numerator, denominator);
else
return integer.ToString(); // just an integer value, e.g. 0, -3, 12...
}
Run Code Online (Sandbox Code Playgroud)
测试
const double cmInInch = 2.54;
// 1 17/64
Console.Write(ToFraction64(3.21 / cmInInch));
// -1 17/64
Console.Write(ToFraction64(-1.26378));
// 3 1/4
Console.Write(ToFraction64(3.25001));
// 3 1/4
Console.Write(ToFraction64(3.24997));
// 5
Console.Write(ToFraction64(5.000001));
// -1/8
Console.Write(ToFraction64(-0.129));
// 1/8
Console.Write(ToFraction64(0.129));
Run Code Online (Sandbox Code Playgroud)