I recently had to make heavy use of Foundation.Decimal, which is cumbersome, because instead of writing let d: Decimal = 25.4, I have to write let d = Decimal(string: “25.4”), or the compiler will push 25.4 through Double, and the result is more like 25.3999996185302734375.
Is there any way to write an initializer that gets handed the literal string in the code for a numeric value, rather than relying on the compiler to first turn it into a float?
No. You can make Decimal conform to ExpressibleByStringLiteral, but there's no way to get a numeric literal as a String. Maybe we could add another FloatLiteralType that would be able to maintain full precision, but I don't think we could update Decimal's conformance to use it. I usually wrap Decimal into type named the way I want, like Money, and make sure that type only conforms to protocols that can accurately model the Decimal.
Unfortunately, there’s no way to wrap Decimal to allow writing a literal floating point number that preserves precision. You have to pass it a string.
I think it would be really cool if there was a way be passed the floating literal string by the compiler. I could add conformance for Decimal in an extension, and various higher-precision libraries (like the one planned for swift-numerics) could take advantage of it, too.
Along similar lines, it is intentional that StaticBigInt cannot represent fractional values. Integer types should not be constructible with fractional literals, and allowing that simply adds unnecessary costs and introduces a new way for construction to fail. It is still a language goal for Swift to someday support dynamically flexible floating-point literals the way it does for integer literals, but that is a separable project from introducing StaticBigInt.
You're right. Wrapping it just allows you to drop the broken ExpressibleByFloatLiteral conformance and add API appropriate for your intended usage that maintains precision, usually by using String, unfortunately.