0

这可能是不可能的,但我想问也无妨。我有一个程序需要将非整数小数转换为八进制表示法。据我所知,Java 只能自动处理整数八进制数。我拼凑了一些东西,其中包括将数字分解为八的幂,就像这样。

.abcd = x * (1/8) + y * (1/64) + z * (1/512) + ......

如果有意义的话,它将显示为“0.xyz”。问题是,这会导致长数字出现大量舍入/截断错误。有一个更好的方法吗?

(编辑)这是我用来处理小数点右侧数字的算法:

double floatPartNum = Double.parseDouble("0." + temps[1]);
     if (floatPartNum > 0) {
        int p = 1;
        result = result + ".";
        while (floatPartNum > 0 && p < 16) {
           double scale = 1/(Math.pow(8, p));
           int modT = (int)( floatPartNum / scale );
           result = result + modT;
           double modScale = (double)modT * scale;
           floatPartNum -= modScale;
           p++;
        }
     }
4

4 回答 4

2

我知道在基本 Java 中没有对八进制数的浮点或定点支持。如果您展示从十进制中提取八进制数字的算法,也许我们可以帮助减少错误。

于 2012-02-14T03:28:54.640 回答
1

p < 16正在人为地截断您的输出。当我在 上尝试您的代码时1.0/3.0,我得到了0.252525252525252,但实际上双精度足以添加三个八进制数字0.252525252525252525,如果您将其更改为p < 20. 但是,如果您担心“长数字”,那么您可能会发现这double还不足以满足您的需求。

顺便说一句,您的循环可以显着简化为:

for(int p = 1; floatPartNum > 0 && p < 20; ++p)
{
    floatPartNum *= 8.0;
    result = result + (int)floatPartNum;
    floatPartNum -= (int)floatPartNum;
}

(经过测试),这消除了所有需要Math.pow等等。(Math.pow通过执行对数和指数运算来工作;当您仅乘以 8 时,这有点过分,并且可能容易舍入。)

于 2012-02-14T15:51:37.983 回答
1

Float 和 Double 类中有一些方法可以让您获得数字的按位表示;例如Double.doubleToLongBits(double)

然后,您可以从双位中提取尾数和指数部分,并将它们转换为您的八进制格式,而不会损失精度。


但是,仅修复您当前的算法可能会更简单。我原以为您应该能够在不损失精度的情况下实施您的方法。(您是否考虑过精度已经丢失的可能性;即在最初产生您的数字的过程/计算中?)

于 2012-02-14T03:52:49.237 回答
0

更像这样的东西怎么样?:

  String result = "";
  double floatPartNum = temps[1];
  if( floatPartNum > 0 )
  {
     int p = 1;
     result = result + ".";
     while( floatPartNum > 0 && p < 16 )
     {
        floatPartNum *= 8.0D;
        int modT = (int)floatPartNum;
        floatPartNum -= modT;
        result = result + modT;

        p++;
     }
  }

引入错误的操作要少得多。(很抱歉,我无法在发布之前测试此代码,我不在我的编程工具附近。)

于 2012-02-14T05:28:15.210 回答