New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
math/big: Rat: add FloatPrec() (int, bool) #50489
Comments
I wrote a very long and complicated answer to this, but perhaps it's better just to state that rather than change FloatString in such a peculiar and possibly incompatible way, a better answer is to add a function that tells you how many bits of precision you'd need. The problem with that is that there is no simple answer in general, as you may have a repeating decimal, but the function could tell you that: func (r *Rat) FloatSize() (digitsLeftOfDecimal, digitsRightOfDecimal int, repeats bool) That solves the problem but I am far from convinced the problem is significant enough to require such a messy fix, either mine or yours. If you want to be clever, you can compute (10 gcd denominator) and get some of the answer yourself, since infinite-length representation only happens when the factors of the denominator are not all factors of the printing base. |
That is a good point and I like the idea of
With messy fix you mean the negative precision proposal or |
Both. As I said, "mine or yours". |
I see. The problem I have is that when marshaling and unmarshaling JSON with large decimal numbers as strings it is useful to have a way to parse them and then marshal them back into the same precision as they came in. Because they are parsed from a fixed length strings I know that I can format them back to one as well (so that there will be no repeats or infinite digits). The issue is only that there is no easy way to do that back conversion. On the other hand I do not want to lose precision if it is not necessary. So having |
I made an implementation with signature |
This seems like an awkward use of big.Rat. Why use big.Rat in this case at all? Why not use json.Number as the round-trippable representation? |
Oh, sorry if that was unclear from the proposal. The roundtrip is the sanity check motivation, if I have a data structure and I read it from the JSON into numbers with |
Do we care about the repeat size or the digits on the left? The finite digits on the right is guaranteed to be 10 log D, which will fit in an int whenever D fits in memory.
that returns 0, false for rats with non-finite float representations? |
Yes, I agree that digits on the left are not important. The implementation I made here has the following signature:
So But maybe my implementation is not as elegant as it could be. But I would be OK with In practice, using the signature from my implementation, I generally do |
@mitar the problem is that there can be >2^64 repeating digits. |
This proposal has been added to the active column of the proposals project |
Sure, the caller of this function would then decide what limits to apply before passing digits further. Or are you saying that |
Yes, the problem is the result does not fit in int, or even int64.
|
I am fine with that. |
For clarity:
|
Does anyone object to FloatPrec as described in #50489 (comment)? |
Few more examples:
|
I disagree about the above examples. If the bool is false, the count is always zero. The number of digits before the repetition begins may not fit in an int64 (I'm not sure) If there is some trivial computation of the non-repeated prefix and it is guaranteed to fit in int64 and it's useful, then maybe we could think about adding it. But none of those three seem to be true. |
With that clarification, does anyone object to adding FloatPrec as in #50489 (comment)? |
I am still not sure this problem is worth solving at all due to its rarity in practice. |
The original message said this was the use case:
I am sympathetic to that and can see it arising in a variety of programs. In fact, it is a bit annoying to me in Ivy that 0.1 + 0.1 = 1/5 instead of 0.2. |
Based on the discussion above, this proposal seems like a likely accept. |
No change in consensus, so accepted. 🎉 |
Change https://go.dev/cl/521235 mentions this issue: |
Update, Mar 2 2022: Current API is at #50489 (comment). -rsc
Currently if I parse string like
123.34
withSetString()
and want to print it back to full precision, one has to manually pick the right precision forFloatString()
function to get that. I propose that insteadFloatString()
should accept negativeprec
parameter. The full semantics ofprec
parameter would then be:prec
, it formats withprec
digits after the radix point, padding with 0 on the right if necessary. The last digit is rounded to nearest, with halves rounded away from zero, if rounding is necessary.prec
is 0, there are no digits after the radix point.prec
is less than 0, then:abs(prec)
number of digits is used after the radix point, rounded the last digit to nearest, with halves rounded away from zero.So
FloatString(3)
for the number above returns123.340
, butFloatString(-3)
return123.34
.big.NewRat(1, 3).FloatString(3)
returns0.333
andbig.NewRat(1, 3).FloatString(-3)
would return0.333
.The text was updated successfully, but these errors were encountered: