简体   繁体   English

如何将一个大数字作为字符串递增,就像它是整数一样?

[英]How to increment a large number as a string as if it were an integer?

I've been trying to think of ways to do it, I can't just convert the string to an int. 我一直在想办法做到这一点,我不能只是将字符串转换为int。 It's too long to be an int, that's the reason I need to do this. 成为一个整数太长了,这就是我需要这样做的原因。 I can do it for single digits, but as soon as I want to add say 10 or 20 I'm not sure how to change my code to allow that. 我可以将其设置为一位数字,但是一旦我想添加10或20,我就不确定如何更改代码以允许这样做。 If I increase the loop it will increase the length of the string and that wouldn't be treating it as an actual number. 如果增加循环,它将增加字符串的长度,并且不会将其视为实际数字。 The reason I include two languages is because I will accept C# or F# code in an answer. 之所以包含两种语言,是因为我将在答案中接受C#或F#代码。

open System

type String with
    member this.Last() =
        this.[this.Length - 1]

let mutable s = "1234567890" // the numbers I will use are a lot bigger than this.

for i in 0 .. 9 do // 9 is max before it increases the length of the string.
    printfn "%s" s

    let last = (s.Last().ToString() |> int) + 1

    s <- s.[0 .. s.Length - 2] + last.ToString()

Console.Read() |> ignore

I doubt there is any situation where using strings to represent numbers would be a good idea - you can use BigInteger to represent and work with large numbers and it supports all numerical operations, not just incrementing by one. 我怀疑在任何情况下使用字符串表示数字是否是一个好主意-您可以使用BigInteger表示并处理大量数字,并且它支持所有数字运算,而不仅仅是增加一个。

However, it is a fun problem, so here is one possible F# solution: 但是,这是一个有趣的问题,因此这是一个可能的F#解决方案:

let incString (s:string) = 
  let rec loop acc carry i (s:string) =  
    match i, carry with 
    | -1, true -> System.String(Array.ofList ('1'::acc))
    | -1, false -> System.String(Array.ofList acc)
    | _ ->
      match s.[i], carry with 
      | '9', true -> loop ('0'::acc) true (i-1) s 
      | c, false -> loop (c::acc) false (i-1) s
      | c, true -> loop (char ((int c) + 1)::acc) false (i-1) s
  loop [] true (s.Length-1) s

incString "9899"

The inner loop function takes the following parameters: 内部loop函数采用以下参数:

  • acc is an accumulator, used to collect digits of the new number (starting from the end) acc是一个累加器,用于收集新数字的数字(从结尾开始)
  • carry is a boolean flag that is true if we want to add 1 to the next number (this is initially true and then it is also true as long as the digits are 9 - because 9 will become 0 and we then need to add to the next digit in the string). carry是一个布尔标志,是true ,如果我们要添加1到下一个数字(这是最初true ,然后它也是true ,只要数字是9 -因为9将成为0 ,我们则需要添加到字符串中的下一位)。

  • i is the current index, starting from the last one i是当前索引,从最后一个索引开始

  • s is the input string representing the original number. s是代表原始数字的输入字符串。

you reverse it into a list of chars the try to increment the lowest digit, if that doesnt work (its a 9), you set the lowest digit to '0' and recurse the tail 您将其反转为字符列表,尝试递增最低位数,如果不起作用(它为9),则将最低位数设置为“ 0”并递归尾部

let inc: string -> string =
    let rec incRev: List<char> -> List<char> =             
        function
        | [] -> [ '1' ]
        | '9' :: cs -> '0' :: incRev cs
        | c :: cs -> char (int c + 1) :: cs
    fun s -> 
        s.ToCharArray() 
        |> Array.toList 
        |> List.rev
        |> incRev
        |> List.rev
        |> Array.ofList
        |> System.String

another probably slightly more efficient answer (I prefer the previous one), but doesnt have all the reversing going on. 另一个可能稍微更有效的答案(我更喜欢上一个),但没有所有反向操作。 you fold from the back of the list of chars assembling an answer and passing the carry digit up to the end. 您可以从字符列表的后面折叠来组合答案,并将进位数字传递到末尾。

let inc2: string -> string =
    let incDigit : (char * (List<char> * char)) -> (List<char> * char) =
        function 
        | (c,(a,'0'))   -> (c :: a,'0')
        | ('9',(a,'1')) -> ('0' :: a,'1')
        | (c,(a,'1'))   -> ((char (int c + 1)) :: a,'0')            
    fun s -> 
        let result = 
            (s.ToCharArray() 
            |> Array.toList 
            |> List.foldBack (fun c state -> incDigit (c,state))) ([],'1')
        result
        |> fst
        |> if (snd result = '1') then (fun cs -> '1' :: cs) else id
        |> Array.ofList
        |> System.String

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM