Typed-struct float32 optimization can lose ≤1 ULP on non-canonical doubles
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Cần làm rõ
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- javascript
- Lĩnh vực
- backend
Hướng nghiên cứu
Bắt đầu từ number path của typed-struct randomAccessStructure và so sánh nó với struct.js của msgpackr v1, sau đó chạy bản tái hiện JavaScript được cung cấp. Done chưa được định nghĩa: issue này nêu rõ việc theo dõi một thay đổi bị trì hoãn, và bất kỳ triển khai nào cũng cần một quyết định tương thích đã được thống nhất cùng các bài kiểm thử cho round trip chính xác và đầu ra giống hệt từng byte.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
The typed-struct (randomAccessStructure) number path stores certain float64 values as a 4-byte float32 field and reconstructs them on decode using the significant-digit rounding heuristic (the mult10 table). For a double that is not the canonical shortest-decimal representative of its decimal value, decode returns the canonical neighbor instead — a loss of up to 1 ULP.
This is the deliberate msgpackr float32 optimization carried over byte-for-byte from msgpackr's struct.js (it is not a structon regression — structon's output is byte-identical to msgpackr v1.11's native randomAccessStructure here). Filing as a tracking issue per discussion; no fix planned right now.
Scope
- Only the typed-struct path is affected. Plain msgpackr/cbor-x number encoding preserves the exact double.
- The same behavior exists in msgpackr v1's
struct.js(the deployed 5.0.x code), so any future change should be considered jointly.
Reproduction
import { Packr } from 'msgpackr';
import { createStructon } from 'structon';
const S = createStructon(Packr);
const enc = new S({ randomAccessStructure: true, useRecords: false });
const v = 1000.0001000000001; // a double adjacent to the 1000.0001 literal
const out = enc.decode(enc.encode({ x: v })).x;
console.log(out); // 1000.0001
console.log(Object.is(out, v)); // false (decoded to the canonical neighbor)
console.log(1000.0001 === v); // false (they are distinct doubles)
1000.0001 (the canonical literal) round-trips exactly; only the non-canonical neighbor canonicalizes.
Why it happens
In the number case, a float32-range value is written as float32, then accepted as num32 if number * mult10[exp] is an integer. That check passes for both a nice decimal and its ULP-adjacent neighbors, so the neighbor decodes to the nice-decimal double.
Possible fix (deferred)
Tighten the float32-acceptance check to require an exact round-trip (decode(float32-bytes) === number) before choosing num32, falling through to float64 otherwise. This would diverge from msgpackr v1's bytes (breaks the byte-identical-output property the test suite asserts), so it's a deliberate-optimization change, not a drop-in fix.
Impact
Low: ≤1 ULP (~1e-13 relative), only on the struct path, only for non-canonical doubles. Not a correctness concern for typical data (e.g. it did not contribute to the typed-struct memory blowup tracked separately).
Filed by Claude (Opus 4.7) on behalf of @kris-zyp during the typed-struct memory investigation.
- Ngôn ngữ chính
- JavaScript
- Star
- 13
- Fork
- 1
- Merge trung bình
- 4 ngày 3 giờ
- Pull request đã merge (30 ngày)
- 2
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
-
good first issue help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
-
cli: `studio --request <missing file>` answers with a raw ENOENT/EISDIR instead of a clear errorĐang mởbug good first issue help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
laaielichter/Ai-edit-studio#81 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
jasonacox/pypowerwall#472 ·
Maintainer thường phản hồi trong vòng 1 ngày