cue icon indicating copy to clipboard operation
cue copied to clipboard

eval: loss of Precision in Arithmetic Operations on 35-Digit Integers

Open takonomura opened this issue 10 months ago • 4 comments

What version of CUE are you using (cue version)?

$ cue version
cue version v0.12.0

go version go1.23.5
      -buildmode exe
       -compiler gc
       -trimpath true
  DefaultGODEBUG asynctimerchan=1,gotypesalias=0,httpservecontentkeepheaders=1,tls3des=1,tlskyber=0,x509keypairleaf=0,x509negativeserial=1
     CGO_ENABLED 1
          GOARCH arm64
            GOOS darwin
         GOARM64 v8.0
cue.lang.version v0.12.0

Does this issue reproduce with the latest stable release?

Yes

What did you do?

exec cue eval
cmp stdout stdout.golden

-- x.cue --
package x

a: 10000000000000000000000000000000001
b: 10000000000000000000000000000000000 + 1
c: 10000000000000000000000000000000002 - 1

// 34-digit integer works
x: 9999999999999999999999999999999998
y: 9999999999999999999999999999999997 + 1
z: 9999999999999999999999999999999999 - 1
-- stdout.golden --
a: 10000000000000000000000000000000001
b: 10000000000000000000000000000000001
c: 10000000000000000000000000000000001
x: 9999999999999999999999999999999998
y: 9999999999999999999999999999999998
z: 9999999999999999999999999999999998

What did you expect to see?

I expected the test to pass. According to https://cuelang.org/docs/reference/spec/#numeric-values, I expected arithmetic operations on integer values to be performed with at least 256-bit precision.

What did you see instead?

$ testscript test.txtar
> exec cue eval
[stdout]
a: 10000000000000000000000000000000001
b: 1.000000000000000000000000000000000e+34
c: 1.000000000000000000000000000000000e+34
x: 9999999999999999999999999999999998
y: 9999999999999999999999999999999998
z: 9999999999999999999999999999999998
> cmp stdout stdout.golden
diff stdout stdout.golden
--- stdout
+++ stdout.golden
@@ -1,6 +1,6 @@
 a: 10000000000000000000000000000000001
-b: 1.000000000000000000000000000000000e+34
-c: 1.000000000000000000000000000000000e+34
+b: 10000000000000000000000000000000001
+c: 10000000000000000000000000000000001
 x: 9999999999999999999999999999999998
 y: 9999999999999999999999999999999998
 z: 9999999999999999999999999999999998

FAIL: test.txtar:2: stdout and stdout.golden differ
failed run

takonomura avatar Feb 27 '25 04:02 takonomura

Thanks for the report @takonomura. Please can you provide some context in which you are running into this? For example, is this a financial application?

I will let @mpvl reply here in the first instance regarding CUE's choice to drop down to float here.

But for now just link https://github.com/cue-lang/cue/issues/1883. And further note that at least I have wondered if there is a place for a mode of CUE which use math/big or similar for all computations, with an acceptance in such a mode that performance will be impacted.

myitcv avatar Feb 27 '25 06:02 myitcv

Please can you provide some context in which you are running into this?

I am trying to perform arithmetic operations on IP addresses by adapting the method described at https://github.com/cue-lang/cue/issues/3142#issuecomment-2110995389. The approach works well for IPv4 addresses (32-bit, 10 digits), but I encountered an issue when applying the same method to IPv6 addresses (128-bit, 39 digits).

takonomura avatar Feb 27 '25 07:02 takonomura

@takonomura I see. I have replied in https://github.com/cue-lang/cue/issues/3142#issuecomment-2708228748. Happy to help move forward getting something added to the standard library if we can agree on a sensible API.

myitcv avatar Mar 08 '25 11:03 myitcv

Here's an example that demonstrates that the + operator really does inappropriately drop down to float precision: it's not just an artifact of the export/display logic:

exec cue export x.cue
cmp stdout stdout.golden

-- x.cue --
import "strconv"

strconv.FormatInt(10000000000000000000000000000000000 + 1, 10)
-- stdout.golden --
"10000000000000000000000000000000001"

The above example fails with:

> exec cue export x.cue
[stderr]
error in call to strconv.FormatInt: cue: exponent should always be nil for integer types:
    ./x.cue:3:1
[exit status 1]
FAIL: /tmp/x.txtar:1: unexpected command failure

rogpeppe avatar Jun 13 '25 10:06 rogpeppe