Localised formatting of UInt64 (or BigInts)

It appears there's no way to render a UInt64 (or similarly large integer type) to a localised string (appropriate thousands separators etc) in the Swift standard library nor Foundation?

The FormatStyle stuff (.formatted(…) etc) is broken for numbers above Int64.max (FB13170519):

let value = UInt64(Int64.max) + 1 // 9223372036854775808
value.formatted(.number) // "9223372036854775807"
value.description // "9223372036854775808"

So, as a workaround, is there a good 3rd party package for this, ideally fully supporting all BinaryIntegers (as I'm most interested in doing this for a BigInt implementation, not UInt64 specifically)?

I'm not sure why, but I think this may be what's happening:
The .formatted(_:) method calls a cached NumberFormatter instance, which means that the UInt64 is casted to an NSNumber internally. NSNumber is toll-free bridged with CFNumber, which is basically this:

enum CFNumber {
  case floating(Double)
  case integer(Int64)

So the conversion to NSCFNumber is probably truncating the number to fit into Int64.

1 Like

However as a quick workaround you can just convert it to Decimal, which has the precision necessary for all UInt64s.

Yeah, but not for arbitrary-precision integers, which is my actual use case. I was just more surprised to find that it's broken for two of the most fundamental integer types in Swift (UInt and UInt64) [than third-party bigint libraries].

Curiously of all the BigInt packages I've reviewed so far - and there are a surprisingly large number in Swift - not a single one supports localised string rendering.

I'm curious if the new [new] Foundation will fix / has fixed this. Alas I have no idea how to utilise it in my app (SwiftUI Mac app) even for exploratory purposes, let-alone to ship (I assume we have to wait some number of years - but hopefully not never - for the new [new] Foundation to actually be integrated into the OSes?).

Ugh, nope, it's broken in exactly the same way. :pensive:

It appears it uses the same C++ ICU library for its actual implementation as does old Foundation, and that library doesn't support large numbers.

I believe Decimal actually has enough precision for UInt128. But for numbers larger than that, yeah I don't really know