Skip to content

Incorrect string formatting for numbers larger than Int64.max (2^63 - 1) #113

Description

@wadetregaskis

description (per CustomStringConvertible) seems to work fine, but of course doesn't produce localised outputs (as expected per its purpose). I want localised outputs, which is normally (for the built-in numeric types) done via the formatted(…) methods. These do exist on BigInt and BigUInt, but produce erroneous results at 2^63 and higher (9,223,372,036,854,775,808).

e.g. 2^63 renders as "9,223,372,036,854,775,807" (which is 2^63 - 1, which happens to be Int64.max).
e.g. 1e25 renders as "9,999,999,999,999,999,000,000,000".

It appears the formatting's precision is somehow limited to the first (highest-order) Int64 word, even though it does show the correct magnitude ("rounding" errors notwithstanding).

Activity

  1. wadetregaskis commented on Sep 14, 2023

    @wadetregaskis
    Author
    import BigInt
    
    extension Foundation.FormatStyle where Self == IntegerFormatStyle<BigUInt> {
        static var number: IntegerFormatStyle<BigUInt> {
            IntegerFormatStyle<BigUInt>()
        }
    }
    
    var hmm: BigUInt = 9_223_372_036_854_775_807
    
    while true {
        let formatted = hmm.formatted(.number.locale(Locale(identifier: "en_US_POSIX")))
    
         if BigUInt(formatted) != hmm {
              print("Broke at \(hmm.description) - \(formatted).")
              break
         }
    
         hmm += 1
    }
  2. wadetregaskis commented on Sep 14, 2023

    @wadetregaskis
    Author

    Note that in the above example I added a number static member to FormatStyle for convenience (as the built-in overloads of number are only for the Swift built-in numeric types), but that's not germane to the problem. If you delete that extension you can't use .number anymore, but can still see the problem with other standard format style conveniences e.g. hmm.formatted(.currency(code: "usd")).

  3. wadetregaskis commented on Sep 14, 2023

    @wadetregaskis
    Author

    Also, IntegerFormatStyle breaks with UInt64 at the same point. So this looks like a bug in the Swift standard library, in which case this GitHub issue is more of an FYI, I suppose. Maybe there's some way to work around the issue, e.g. provide a FormatStyle implementation specifically for BigInt / BigUInt?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions