How to deal with Precision loss in scores in sorted sets for geospatial data

I’m stuck on Stage #hb5 (GEOSPATIAL SCORING)

Since scores in sorted set can be fractional values, Im storing score as a 64 bit floating point number which is f64 in rust,

the problem is while converting between 64 bit INT scores which are being used in geospatial scoring and storing them as f64 i think im losing precision due to which during encoding/decoding im getting coords that vary by more than 1e-6.

And here’s a snippet of my logs:

I have the same issue with Rust. The 6th decimal often deviates in the end result of the decoding process (u64 score input for decode is correct). The stage uses ZADD to add ‘hardcoded’ scores so encoding part can’t affect it.

I passed the stage but it required me to submit about 10 times in a row before I got lucky.

The precision requirement probably needs to be lowered.

do you know how official implementation handles this ? do they just allow enough precision loss or are they doing something differnet ?

I don’t think there’s anything you can do except wait for some kind of change to the tester (less precision is probably the only option).

The tester looks identical to the official redis implementation. The only difference I could spot is order of operations when converting degrees to radians but that shouldn’t make any significant difference.

I tried doing all calculations with very high precision decimal types but the result is the same. I also tried using a 100% identical implementation as the tester (adding an extra unnecessary conversion from degrees to radians which redis also does) but the result doesn’t change.

Maybe Go (tester) is doing something weird here with f64 calculations.

interesting, thanks for sharing

I ran this test against official redis server and it fails

[stage-806] Running tests for Stage #806: GEOPOS-2
[stage-806] $ ./your_program.sh
[your_program] 9179:C 30 Aug 2025 20:25:29.214 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
[your_program] 9179:C 30 Aug 2025 20:25:29.214 * Redis version=8.0.1, bits=64, commit=00000000, modified=1, pid=9179, just started
[your_program] 9179:C 30 Aug 2025 20:25:29.214 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
[your_program] 9179:M 30 Aug 2025 20:25:29.214 * monotonic clock: POSIX clock_gettime
[your_program] 9179:M 30 Aug 2025 20:25:29.214 * Running mode=standalone, port=6379.
[your_program] 9179:M 30 Aug 2025 20:25:29.214 # WARNING: The TCP backlog setting of 511 cannot be enforced because kern.ipc.somaxconn is set to the lower value of 128.
[your_program] 9179:M 30 Aug 2025 20:25:29.214 * Server initialized
[your_program] 9179:M 30 Aug 2025 20:25:29.214 * Loading RDB produced by version 8.0.1
[your_program] 9179:M 30 Aug 2025 20:25:29.214 * RDB age 5 seconds
[your_program] 9179:M 30 Aug 2025 20:25:29.214 * RDB memory usage when created 0.83 Mb
[your_program] 9179:M 30 Aug 2025 20:25:29.214 * Done loading RDB, keys loaded: 4, keys expired: 0.
[your_program] 9179:M 30 Aug 2025 20:25:29.214 * DB loaded from disk: 0.000 seconds
[your_program] 9179:M 30 Aug 2025 20:25:29.214 * Ready to accept connections tcp
[stage-806] [client] $ redis-cli ZADD strawberry 224085498881558 banana
[stage-806] [client] Sent bytes: "*4\r\n$4\r\nZADD\r\n$10\r\nstrawberry\r\n$15\r\n224085498881558\r\n$6\r\nbanana\r\n"
[stage-806] [client] Received bytes: ":1\r\n"
[stage-806] [client] Received RESP integer: 1
[stage-806] [client] ✔︎ Received 1
[stage-806] [client] > ZADD strawberry 2451251516498654 strawberry
[stage-806] [client] Sent bytes: "*4\r\n$4\r\nZADD\r\n$10\r\nstrawberry\r\n$16\r\n2451251516498654\r\n$10\r\nstrawberry\r\n"
[stage-806] [client] Received bytes: ":1\r\n"
[stage-806] [client] Received RESP integer: 1
[stage-806] [client] ✔︎ Received 1
[stage-806] [client] > GEOPOS strawberry strawberry banana
[stage-806] [client] Sent bytes: "*4\r\n$6\r\nGEOPOS\r\n$10\r\nstrawberry\r\n$10\r\nstrawberry\r\n$6\r\nbanana\r\n"
[stage-806] [client] Received bytes: "*2\r\n*2\r\n$17\r\n69.38464611768723\r\n$18\r\n-64.62180725981094\r\n*2\r\n$18\r\n-114.2862144112587\r\n$19\r\n-59.176273154394956\r\n"
[stage-806] [client] Received RESP array: [
[stage-806] [client]   [
[stage-806] [client]     "69.38464611768723",
[stage-806] [client]     "-64.62180725981094"
[stage-806] [client]   ],
[stage-806] [client]   [
[stage-806] [client]     "-114.2862144112587",
[stage-806] [client]     "-59.176273154394956"
[stage-806] [client]   ]
[stage-806] [client] ]
[stage-806] Expected 69.38464726698169 (± 1e-06), got 69.38464611768723
[stage-806] Test failed
[stage-806] Terminating program
[your_program] 9179:signal-handler (1756565729) Received SIGTERM scheduling shutdown...
[your_program] 9179:signal-handler (1756565729) Received SIGTERM scheduling shutdown...
[your_program] 9179:M 30 Aug 2025 20:25:29.316 * User requested shutdown...
[your_program] 9179:M 30 Aug 2025 20:25:29.316 * Saving the final RDB snapshot before exiting.
[your_program] 9179:M 30 Aug 2025 20:25:29.322 * DB saved on disk
[your_program] 9179:M 30 Aug 2025 20:25:29.322 # Redis is now ready to exit, bye bye...
[stage-806] Program terminated successfully

Fix: GeoPosTestCase: fixed bug for asserting responses by UdeshyaDhungana · Pull Request #221 · codecrafters-io/redis-tester · GitHub this PR fixes the bug waiting for it be merged.

Yeah I just noticed you posted it in the other thread. That explains the deviation. The tester seems to be skipping the whole encode/decode part currently and expecting values that haven’t gone through the precision loss during encoding.

Since the free challenge is changing soon:
If you don’t want to wait use a high precision decimal type (eg. rust_decimal or num crate in rust or just Decimal in C#) for the decode part and submit 5-10 times until it passes. The later stages don’t have issues, although submitting them will take 5-10 tries again due to the geopos tests failing. It might be possible with normal f64 calculations but the difference to tester seemed to be slightly larger like that.

too late, i was using C so not sure if it was possible anyway, thanks though

Hi Everyone! We’ve upgraded our tester to include a fix for this test case here.

Please give it a re-try and let us know how it goes.

1 Like

free trial’s over twin :folded_hands: :sob:

Tried twice, passed both times. Seems fine now.

2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.