C:打印一个以 10 为基数的 BigInteger
我正在使用这个结构来表示 128 位整数:(
typedef struct {
uint64_t low, high;
} uint128;
除非你能给我指出一个快速的 128 位整数库,否则我无法更改它)
现在我想使用 printf
打印这样一个以 10 为基数的值。我可能需要除以 10 才能做到这一点,但尚未实现除法。
我该怎么做?该解决方案不必非常高效,只要它有效即可。
编辑:我喜欢你提出的所有解决方案。你太棒了。
I am using this struct to represent 128bit integers:
typedef struct {
uint64_t low, high;
} uint128;
(Unless you can point me to a fast 128bit integer library I can not change that)
Now I want to print such a value in base 10, using printf
. I probably need division by 10 to do that, but no division is implemented yet.
How can I do this? The solution does not have to be super efficient, as long as it works.
EDIT: I like all solutions you came up with. You are awesome.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您不想实现 128 位值的除法,您可以预先计算几个(~40)代表 10 次幂的 128 位值,并使用减法。
实际上只有较高的 qword 才会以这种方式处理,因为对于较低的部分,您可以使用
printf("%I64d")
。编辑:这是一个示例(它将仅使用
char
上的算术打印short
):您可以使用较少数量的预先计算的 10 次幂,但这会使速度变慢(例如,以 100 为步长将使
ctr
处于0..99
范围内。If you don't want to implement division for 128bit value, you could precompute several (~40) 128 bit values that represents powers of 10, and use substraction.
Actually only higher qword have be processed in this way, because for lower part you can use
printf("%I64d")
.EDIT: here is an example (it will print a
short
using only arithmetics onchar
):You can use smaller number of precomputed powers of 10, but it will make it slower (ex, having them in steps of 100 will make
ctr
to be in range0..99
.假设您已经实现了对
uint128
执行数学计算的函数,您可以将数字分成 3 部分并使用 printf 的内置 64 位打印功能。由于最大的 64 位数字有 20 位长,这意味着所有 19 位十进制数都可以这样打印,但由于最大的 128 位数字有 39 位长,所以我们不能将其分成两部分,因为我们最终得到的 20 位数字可能比最大的 64 位数字大。这是一种方法,首先除以 1020 以获得不大于 3,402,823,669,209,384,634 的商。然后,我们将余数(本身不大于 1020)除以 1010,得到另一个商,余数均小于 1020,即两者都适合 64 位整数。
Assuming you've already implemented functions to perform math on
uint128
, you could break the number up into 3 parts and use the built-in 64-bit printing capabilities of printf. Since the largest 64-bit number is 20 digits long, that means all 19-digit decimal numbers can be printed that way, but since the largest 128-bit number is 39 digits long, we can't break it up into only 2 parts, since there's a chance that we might end up with a 20 digit number bigger than the largest 64-bit number.Here's one way to do it, dividing first by 1020 to get a quotient no larger than 3,402,823,669,209,384,634. We then divide the remainder (itself no larger than 1020) by 1010 to get another quotient and remainder each less than 1020, which both fit in a 64-bit integer.
您可以使用乘法来打印数字。
由于 2128 约为 340E36,因此首先通过将数字与 100E36、200E36 和 300E36 边界进行比较来确定前导数字。写入一个数字并减去最近的较小边界。例如如果数字是 234.6776E36,那么最近的较小边界是 200E36,数字是“2”,相减后应该得到 34.6776E36。
现在通过与数字 10E36...90E36 进行比较来获取下一个数字。当然是128位比较。如上所述,写入一个数字并减去最小边界。 (对于 34.6776E36,上面的数字是“3”,边界是 30E36,余数是 4.6776E36)
然后将数字乘以 10,并从阶段 2 开始重复,总共 38 次打印每个数字。 (4.6776E36 -> 46.776E36...)
UPD:添加了我首先错过的减法。以及例子。
UPD2:第 1 位数字需要专用步骤,因为如果将其旁边的数字相乘,如果余数大于 34E36,则应该会溢出。
You may use multiplication to print a number.
As 2128 is about 340E36, first determine leading digit, by comparing number with 100E36, 200E36 and 300E36 boundaries. Write a digit and subtract nearest lesser boundary. E. g. If number is 234.6776E36 then nearest lesser bounary is 200E36, digit is '2' and after subtraction you should get 34.6776E36.
Now get next digit using comparison with numbers 10E36...90E36. Of course it is 128 bit comparison. Write a digit and subtract hearest lesser boundary as above. (For 34.6776E36 from above digit is '3', boundary is 30E36 and remainder is 4.6776E36)
Then multiply number by 10 and repeat from stage 2, total 38 times to print each digit. (4.6776E36 -> 46.776E36...)
UPD: Added subtraction I missed first. And examples.
UPD2: The need of dedicated step for 1-st digit is jus because if you multiply the number next to it you should get an overflow, if remainder is greater than 34E36.