gpt4 book ai didi

java - 有没有更快的方法将十六进制小数部分转换为十进制?

转载 作者:行者123 更新时间:2023-12-01 14:20:36 27 4
gpt4 key购买 nike

我编写了一个程序,可以生成十六进制的 pi 数字。每隔一段时间,在基准值下,我想将我拥有的十六进制值转换为十进制值并将其保存到文件中。目前我正在使用 BigDecimal 通过以下代码进行数学运算:

private static String toDecimal(String hex) {
String rawHex = hex.replace(".", "");
BigDecimal base = new BigDecimal(new BigInteger(rawHex, 16));
BigDecimal factor = new BigDecimal(BigInteger.valueOf(16).pow(rawHex.length() - 1));
BigDecimal value = base.divide(factor);
return value.toPlainString().substring(0, hex.length());
}

请注意,此方法仅适用于整数部分为一位的十六进制值,包括 pi,请勿复制粘贴以供一般使用。

所以这段代码工作正常,但对于最新的基准,250 万位,转换需要 11.3 小时才能完成。

有没有更快的方法来手动执行此操作?

我尝试将第一个小数位除以 16,将第二个小数位除以 16^2,等等,但这很快就会失控。也许有某种方法可以将数字移回位以保持除数较低?但可能需要处理 n+1、n+2、n+3 等数字以获得正确的 n 值。

最佳答案

首先,我认为您的函数 toDecimal 是错误的,因为它没有正确转换输入 ".1a"(它偏离了 16 倍),例如, 并为输入 ".800" 抛出异常。第三行应该是:

BigDecimal factor = new BigDecimal(BigInteger.valueOf(16).pow(rawHex.length()));

异常产生于:

return value.toPlainString().substring(0, hex.length());

转换后的值可能比输入值短,您会得到一个 java.lang.StringIndexOutOfBoundsException

继续:

事实上,我没有根据您当前的方法对其进行基准测试;我只是将此作为“思考的食物”。在这里,我正在做乘法,因为 child 在学校被教导这样做,在你的情况下,我们有一个大循环来产生一个数字。但是,如果您能以某种方式对其进行调整以使用 BigDecimal(尚不清楚您会怎么做),它可能会比您当前的方法更快(真正需要的是 BigHexadecimal 类)。

可以观察到,可以使用乘法将分数从一个基数转换为另一个基数。在这种情况下,我们有以下十六进制分数(我们可以忽略整数部分,在转换 pi 时为 3):

.h1h2h3h4 ... h n

其中 hn 是第 n 个十六进制“半字节”。

我们希望将上面的小数转换成下面的小数:

.d1d2d3d4 ... d n

其中 dn 是第 n 个十进制数字。

如果我们将两个数量都乘以 10,我们将得到:

h'1.h'2h' 3h'4 ... h'n
素数 (`) 表示乘法后我们有全新的十六进制半字节值。

d1.d2d3d4 ... d n
乘以 10 只是将小数点向左移动一位。

我们必须注意,小数点左边的数量必须相等,即 d1 == h'<子>1 。因此,我们反复将十六进制小数乘以 10,每次乘以整数部分作为转换的下一个十进制数字。我们重复此操作,直到我们的新十六进制分数变为 0 或产生了任意数量的十进制数字:

See Java Demo

class Test {

private static String toDecimal(String hex, int numberDigits) {
/* converts a string such as "13.1a" in base 16 to "19.1015625" in base 10 */
int index = hex.indexOf('.');
assert index != -1;
StringBuilder decimal = new StringBuilder((index == 0) ? "" : String.valueOf(Integer.parseInt(hex.substring(0, index), 16)));
decimal.append('.');
int l = hex.length() - index - 1;
assert l >= 1;
int firstIndex = index + 1;
int hexDigits[] = new int[l];
for (int i = 0; i < l; i++) {
hexDigits[i] = Integer.parseInt(hex.substring(i + firstIndex, i + firstIndex + 1), 16);
}
while (numberDigits != 0 && l != 0) {
int carry = 0;
boolean allZeroes = true;
for (int i = l - 1; i >= 0; i--) {
int value = hexDigits[i] * 10 + carry;
if (value == 0 && allZeroes) {
l = i;
}
else {
allZeroes = false;
carry = (int)(value / 16);
hexDigits[i] = value % 16;
}
}
numberDigits--;
if (carry != 0 || (numberDigits != 0 && l != 0))
decimal.append("0123456789".charAt(carry));
}
return decimal.toString();
}

public static void main(String[] args) {
System.out.println(toDecimal("13.1a", 15));
System.out.println(toDecimal("13.8", 15));
System.out.println(toDecimal("13.1234", 15));
}

}

打印:

19.1015625
19.5
19.07110595703125

关于java - 有没有更快的方法将十六进制小数部分转换为十进制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63454722/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com