c# – 将非常大的数字转换为基数为10的字符串

前端之家收集整理的这篇文章主要介绍了c# – 将非常大的数字转换为基数为10的字符串前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
一个整数测量4个字节.在我的例子中,我的数字为1 MB.如何快速将它们转换为人类可读的十进制数?

该数字出现在包含大小项的uint []数组中.

解决方法

我不知道这是否更快,但这里是delphi中的一个例子,我很久以前曾写过将大的int作为字符串处理(非常快速和脏) – 这是128bit uint但你可以无限延长
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的幂

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)

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

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 ……好吧,它添加了两个十进制字符串:

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;

这些函数允许您对几乎任意大的整数执行基本算术作为字符串.当然,当数字位数太大而无法索引数组时,你会碰到另一面墙.

这是一个除以二,顺便说一句(对于另一种方式很有用……).我这里不处理奇数.

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万位长的二进制字符串尝试了这个,它很慢!真的,这并不奇怪.这是完全未经优化的代码,有很多低调的果实可供选择以加快速度.尽管如此,我还是忍不住觉得这是你可能想要在完全优化的装配中编写的问题的种类(或规模).个别操作很小但是必须多次完成 – 这些咒语要求组装.多线程当然也可以在这里使用.

猜你在找的C#相关文章