如何将极大(> 1MB)的十进制数转换为字节/十六进制/二进制数?
例如,数字“300”应转换为{0x01,0x2C}。字节顺序无关紧要,{0x2C,0x01}也没问题。
源数字存储在准备好的文件中(没有puntuation,空格或换行符)。最大的是just over 17MB,虽然我不能排除将来会有100MB的数字。目的地也是一个文件。
是否有一种不需要多长时间的方法,或者在 需要多长时间的情况下是不安全的?
我担心使用BigInteger
会花费很长时间而不是失败保存(即如果出现问题我无法恢复中途)
我不反对实现我自己的算法,虽然我正在寻找比'检查奇数,除以2'更有效的东西。我已经看到了一个非常有效的二进制到BCD的实现,Shift and Add-3算法,我正在寻找一个反向的类似有效的实现。
对于同样支持定点数的实现的额外荣誉(1位数和其余小数,例如。 Pi)。
答案 0 :(得分:1)
对我来说,BigInteger
会在~39秒内将1M数字转换为byte []
。对你来说太过分了吗?
Random r = new Random ();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000000; i++)
sb.append ("0123456789".charAt(r.nextInt(10)));
long t = System.currentTimeMillis();
BigInteger bi = new BigInteger (sb.toString());
byte [] bytes = bi.toByteArray();
System.out.println(System.currentTimeMillis() - t);
关于小数。让我们假设您在<n digits>.<m digits>
格式中有一个大小数。您希望在点后用k
位将其转换为二进制。您需要求解一个等式:D/(10^m) = X/(2^k)
,其中X是整数。这里D是没有点的十进制数(十进制的尾数),X是没有点的二进制数(二进制的尾数)。方程很容易解决:X ~ round(D*(2^k)/(10^m))
。 X必须是整数,因此我们添加了round()
。
例如,您需要将12.34转换为二进制,并在点后转换为3位。
n = 2
m = 2
D = 1234
k = 3
X ~ round(D*(2^k)/(10^m)) = round(1234 * 8 / 100) = round(98.72) = 99 = 1100011b
请记住,我们想要点后3位,所以我们的答案是12.34~1100.011b
所有这些计算都可以使用BigInteger完成。
答案 1 :(得分:0)
是否有一种不需要多长时间的方法,或者在需要多长时间的情况下是安全的?
不。
将十进制数转换为二进制包括重复将一个大数乘以10.如果您有数百万个数字,则需要数百万次乘法来执行非常大的数字。
然而,听起来你实际上没有对这些非常大的数字进行过转换,而你只是猜测它需要很长时间。在进一步讨论之前,我强烈建议您对此操作进行基准测试,以了解实际需要多长时间。 (米哈伊尔的答案说约39秒,但他编写的代码没有考虑到JVM的预热。)
或者更好的是,使用BigInteger和 profile 对整个应用程序进行编码,以确定是否存在性能问题,以及实际性能瓶颈在哪里。