将非常大的数字转换为以10为底的字符串 [英] Convert very huge number to base 10 string
问题描述
一个整数为4个字节.在我的示例中,我的数字为1 MB.如何将它们转换为快速的人类可读的十进制数字?
An integer measures 4 bytes. In my example I have numbers measuring 1 MB. How can I convert them to a human readable decimal number fast?
该数字出现在包含Size
个项目的uint[]
数组中.
The number is present in uint[]
Array containing Size
items.
推荐答案
我不知道这样做是否更快,但这是我很久以前在delphi中编写的一个示例,用于将大整数作为字符串处理(非常快和肮脏)-这是用于128位uint的,但您可以无限期扩展它
I don't know if this is any faster, but here is an example in delphi I wrote a long time ago to handle big ints as strings (VERY quick and dirty) - this was for 128bit uint but you could extend it indefinitely
Function HexToBinShort(hex:integer):string;
begin
case hex of
0: result:='0000'; //convert each hex digit to binary string
1: result:='0001'; //could do this with high-nybble and low nybble
2: result:='0010'; //of each sequential byte in the array (mask and bit shift)
3: result:='0011'; //ie: binstring:=binstring + HexToBinShort(nybble[i])
4: result:='0100'; //but must count DOWN for i (start with MSB!)
5: result:='0101';
6: result:='0110';
7: result:='0111';
8: result:='1000';
9: result:='1001';
10: result:='1010';
11: result:='1011';
12: result:='1100';
13: result:='1101';
14: result:='1110';
15: result:='1111';
end;
end;
然后采用连接的二进制字符串,并在每次看到"1"时加2的幂
Then take the concatenated binary string and add powers of two each time you see a '1'
Function BinToIntString(binstring:string):string;
var i, j : integer;
var calcHold, calc2 :string;
begin
calc2:=binstring[Length(binstring)]; // first bit is easy 0 or 1
for i := (Length(binstring) - 1) downto 1 do begin
if binstring[i] = '1' then begin
calcHold:=generateCard(Length(binstring)-i);
calc2 := AddDecimalStrings(calcHold, calc2);
end;
end;
result:=calc2;
end;
generateCard用于创建2 ^ i(对于i> 0)的十进制字符串表示形式
generateCard is used to create a decimal string representation of 2^i (for i>0)
Function generateCard(i:integer):string;
var j : integer;
var outVal : string;
begin
outVal := '2';
if i > 1 then begin
for j := 2 to i do begin
outVal:= MulByTwo(outVal);
end;
end;
result := outVal;
end;
和MulByTwo将十进制字符串乘以2
and MulByTwo multiplies a decimal string by two
Function MulByTwo(val:string):string;
var i : integer;
var carry, hold : integer;
var outHold : string;
var outString :string;
var outString2 : string;
begin
outString:= StringOfChar('0', Length(val) + 1);
outString2:= StringOfChar('0', Length(val));
carry :=0;
for i := Length(val) downto 1 do begin
hold := StrToInt(val[i]) * 2 + carry;
if hold >= 10 then begin
carry := 1;
hold := hold - 10;
end else begin
carry := 0;
end;
outHold := IntToStr(hold);
outString[i+1] := outHold[1];
end;
if carry = 1 then begin
outString[1] := '1';
result := outString;
end else begin
for i := 1 to length(outString2) do outString2[i]:=outString[i+1];
result := outString2;
end;
end;
最后-AddDecimalStrings ...好吧,它添加了两个十进制字符串:
And finally - AddDecimalStrings...well, it adds two decimal strings :
Function AddDecimalStrings(val1, val2:string):string;
var i,j :integer;
var carry, hold, largest: integer;
var outString, outString2, bigVal, smVal, outHold:string;
begin
if Length(val1) > Length(val2) then begin
largest:= Length(val1);
bigVal := val1;
smVal := StringOfChar('0', largest);
j:=1;
for i := (largest - length(val2) +1) to largest do begin
smVal[i] := val2[j];
j:=j+1;
end;
end else begin
if length(val2) > Length(val1) then begin
largest:=Length(val2);
bigVal:=val2;
smVal := StringOfChar('0', largest);
j:=1;
for i := (largest - length(val1) +1) to largest do begin
smVal[i] := val1[j];
j:=j+1;
end;
end else begin
largest:=length(val1);
bigVal:=val1;
smVal:=val2;
end;
end;
carry:=0;
outString:=StringOfChar('0', largest +1);
outString2:=StringOfChar('0', largest);
for i := largest downto 1 do begin
hold := StrToInt(bigVal[i]) + StrToInt(smVal[i]) + carry;
if hold >=10 then begin
carry:=1;
hold := hold - 10;
end else begin
carry:=0;
end;
outHold:= IntToStr(hold);
outString[i+1]:=outHold[1];
end;
if carry = 1 then begin
outString[1] := '1';
result := outString;
end else begin
for i := 1 to length(outString2) do outString2[i]:=outString[i+1];
result := outString2;
end;
end;
这些函数使您可以对几乎任意大的整数(如字符串)执行基本算术运算.当然,当位数太大而无法索引数组时,您会碰到另一堵墙.
These functions allow you to perform basic arithmetic on almost arbitrarily large integers as strings. You hit another wall when the number of digits is too big to index an array with, of course.
这里是除以二,顺便说一句(对其他方法很有用...).我在这里不处理奇数.
Here's a divide by two, btw (useful for going the other way...). I don't handle odd numbers here.
Function DivByTwo(val:string):string;
var i : integer;
var hold : integer;
var outHold : string;
var outString, outString2 :string;
begin
outString:=StringOfChar('0',Length(val));
for i := Length(val) downto 1 do begin
if StrToInt(val[i]) mod 2 = 0 then begin
hold:= Math.Floor(StrToInt(val[i]) / 2);
outHold:= IntToStr(hold);
outString[i]:=outHold[1];
end else begin
hold:= Math.Floor((StrToInt(val[i]) - 1) / 2);
outHold:=IntToStr(hold);
outString[i]:= outHold[1];
if i <> Length(val) then begin
hold:= StrToInt(outString[i+1]) + 5;
outHold:= IntToStr(hold);
outString[i+1] := outHold[1];
end;
end;
end;
outString2:=StringOfChar('0',Length(val)-1);
if (outString[1] = '0') and (length(outString) > 1) then begin
for i := 1 to length(outString2) do outString2[i]:=outString[i+1];
result:=outString2;
end else begin
result:=outString;
end;
end;
我刚刚用一个900万位长的二进制字符串尝试了它,而且速度太慢了!不足为奇,真的.这是完全未优化的代码,有很多容易实现的地方可以选择,以加快处理速度.尽管如此,我还是忍不住觉得这是您可能要(至少部分地)在完全优化的程序集中编写的问题的类型(或规模).单个操作很小,但是必须执行多次-这意味着乞求组装.当然,这里也可以利用多线程.
I just tried this with a 9million bit long binary string and it is ludicrously slow! Not surprising, really. This is completely unoptimized code which has a lot of low hanging fruit to pick at for speeding things up. Still, I can't help but feel that this is the kind (or scale) of problem that you would probably want to write, at least partially, in fully optimized assembly. The individual operations are small but they must be done many times - that spells begging for assembly. Multithreading could certainly be leveraged here too.
这篇关于将非常大的数字转换为以10为底的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!