【问题标题】:Java Fraction Base Conversion [closed]Java分数基转换[关闭]
【发布时间】:2019-08-14 17:03:45
【问题描述】:

我想将源基数转换为目标基数,但我遇到了分数问题。当我尝试将 10.234 (base10) 转换为 base 7 = 13.14315 时,它工作得很好,或者 aaaaa.0 (base16) 到 base 24 = 22df2 它也有效。

但是当我尝试将 aaaaa.cdefb0 (base16) 转换为 base 24 = 22df2.j78da 时,它不起作用。我无法计算分数部分,我得到22df2 作为答案

我的基本转换代码:

private static String baseConversion(String number,
                                         int sBase, int dBase) {
        return Long.toString(
                Long.parseLong(number, sBase),
                dBase);
    }

我的分数转换代码:

private static String fractionConversion(double fraction, int dBase) {
        StringBuilder output = new StringBuilder(".");

        for (int i = 0; i < PRECISION; i++) {
            fraction *= dBase;
            output.append(Long.parseLong(Integer.toString((int) fraction)));
            fraction -= Long.parseLong(Integer.toString((int) fraction));
        }

        return output.toString();
    }

【问题讨论】:

  • aaaaa in base 16 是 699050 in base 10
  • @Rogue 好的,但我对此没意见

标签: java base-conversion


【解决方案1】:

在下面的代码中,您应该为基数附加一个符号,而不是数字。使用该数字索引到基数的符号数组中。

我建议使用整数进行余数和乘积计算,因为使用浮点值最终会丢失精度。

        for (int i = 0; i < PRECISION; i++) {
            fraction *= dBase;

            // what are you appending here?  It should be a symbol
            output.append(Long.parseLong(Integer.toString((int) fraction)));

            fraction -= Long.parseLong(Integer.toString((int) fraction));
        }

这里有一个更完整的例子。

  static String symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

   // assumes a string in the form of .293093
   // number of places
   // destination radix.
   public static String expand(String decimalFraction, int places, int dr) {

      decimalFraction = decimalFraction.substring(1); // ignore decimal point
      int numerator = Integer.parseInt(decimalFraction);
      int denominator = (int) Math.pow(10, decimalFraction.length());
      StringBuilder sb = new StringBuilder(".");
      for (int i = 0; i < places; i++) {
         numerator *= dr;
         sb.append(symbols.charAt((int) (numerator / denominator)));
         numerator %= denominator;
         if (numerator == 0) {
            break;
         }
      }
      return sb.toString();
   }

【讨论】:

  • 抱歉,我还是想不通,这对你来说可能很明显,但是我怎样才能将 af.xy(base 35) 转换为 17 呢?我试着把“int numerator = Integer.parseInt(decimalFraction, 35);”但它给出了 IndexOutOfBoundsException
【解决方案2】:

我真的不建议这样做,但无论如何我都会回答这个问题。

我会简单地将这两个数字分开并分别处理。首先,分数在以 10 为基数之外的工作方式不是尾随数字的 1 对 1 转换。以 10 为底的 .25 不是二进制的 .11001,而是 .01

您的数字中的每个小数位都代表一个新的量级;以 10 为底,其值为 10^-110^-2 等。当你改变基数时,你仍然会改变幅度,但速度不同:2^-1,等等。

.25 因此类似于以 10 为底的 2/10 + 5/100 和以 2 为底的 0/2 + 1/4。这会导致一个新问题,如果分数的除数不是新基数的幂,通常得到一个无理数。 1/20 在十进制中是 .05,但在基数 2 中是:

0.00 0011 0011 0011 //endless

这或多或少导致了为什么小数通常不会在基数之间转换。您将失去精度,这不是一项小任务。但本质上,算法对话与整数相同,但不是将数字除以基数并使用余数作为输出,而是乘以基数并使用除法作为输出。

int decimalPart = ...; //for example, "375", represents .375 or 3/8
int magnitude = Math.pow(10, ("" + decimalPart).length());
int newBase = 2; //again, bases that don't divide into each other will be messy, like 7 and 10

StringBuilder out = new StringBuilder();
//The below should be limited for precision, or you may loop forever
while (decimalPart > 0) {
    decimalPart *= newBase;
    out.append(decimalPart / magnitude);
    decimalPart %= magnitude.
}
String result = sb.toString();
//"375" -> "011"

【讨论】:

  • 你基本上重复了我的回答。
  • 我自己在手机上输入了答案,这只是用于转换非小数的相同过程的反转。我可以说你只是重复了一遍;这不是一个固有的复杂解决方案。此外,我的大部分答案都是在解释数学部分。
猜你喜欢
  • 2021-03-09
  • 2012-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-09
相关资源
最近更新 更多