Skip to content
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: (*Float).Text always rounds #50548

Closed
nonzerofloat opened this issue Jan 11, 2022 · 4 comments
Closed

math/big: (*Float).Text always rounds #50548

nonzerofloat opened this issue Jan 11, 2022 · 4 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.

Comments

@nonzerofloat
Copy link

nonzerofloat commented Jan 11, 2022

What version of Go are you using (go version)?

I'm using go.dev/play (2022-01-01 15:00)

Does this issue reproduce with the latest release?

https://go.dev/play/p/S-nYwa_t_uV

What operating system and processor architecture are you using (go env)?

I'm using go.dev/play (2022-01-01 15:00)

What did you do?

x = 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 (150 digits)

I want to find the cubic root of x and need the exact number up to 10 decimal points. Thus the appropriate choice for the rounding is ToZero rounding mode, not ToNearestToEven.

The cubic root of x up to 600 decimal places is
 
99999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999966666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666655555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555549382716049382716049382716049382716049382716049382716049382716049382716049382716049382716049382716049382716049382716049382716049382716049382716049383

What did you expect to see?

Edit: Let z be the cubic root of x and of type *big.Float.
I expect z.SetMode(big.ToZero).Text('f', 10) returns "99999999999999999999999999999999999999999999999999.9999999999"

What did you see instead?

(*Float).Text has no flexible rounding options. It just rounds with NearestEven.

z.SetMode(big.ToZero).Text('f', 10) returns "100000000000000000000000000000000000000000000000000.0000000000"

And z.Text('f', 550) returns the correct value because the digit after 550 decimal point do not affect.

It's the problem. (*Float).Text shall handle RoundingMode.

@dr2chase dr2chase added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Jan 13, 2022
@dr2chase
Copy link
Contributor

I think this is working as intended, and is essentially

  1. a request for a specification change and
  2. would modify the behavior of existing programs if implemented in this form.

@griesemer might also have opinions on this.

@nonzerofloat
Copy link
Author

*big.Float supports many operations with various rounding options and .Text is an operation of it though it is somewhat different. It is not natural the .Text operation does not consider rounding options.

This issue could be regarded as a request for a specification change if the existing behaviour is intended. If intended, the documentation should mention how rouding issues is treated, but don't. It's a bug that is cheap to fix.

@nonzerofloat
Copy link
Author

If this behaviour isn't intended, we might add .TextRounding() method. The issue is beyond a bug.

@griesemer
Copy link
Contributor

Rounding of textual output is not "cheap to fix" (it's subtle at the very least) as rounding happens in the output base (base 10) for which only one rounding mode (to nearest even) is implemented - and it is completely unrelated to RoundingMode.

Being able to provide a rounding mode would require a new method (as suggested). That requires a proposal. But read on.

The purpose of the Text function is to provide a decimal approximation (or exact hexadecimal representation) of a binary floating point value. That decimal value is supposed to be the the closest value (given precision limits in the number of digits) to the binary value. Rounding is needed when the digits past the precision are not all zero. Only if those digits are a 5 followed by all zeros (the 0.5 case), i.e. when we're exactly in the middle between two decimal numbers that would fit the desired precision and which both are equally far away from the actual binary floating-point number, makes the choice of rounding mode a difference - this is exceedingly rare. In all other cases we either round up or down no matter any rounding mode. Anything else would lead to a result that is not the closest possible to the binary floating point value. In the .5 case one might round up or down, and currently we round to nearest even, which seems the most sensible approach.

Being able to provide a rounding mode makes sense when one does (repeated) floating-point operations, but you're not making floating-point operations with the decimal number.

In summary, I don't see a bug here; but perhaps a misunderstanding of how floating-point operations are working.

@golang golang locked and limited conversation to collaborators Jan 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants