惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Full Disclosure
博客园 - 三生石上(FineUI控件)
MyScale Blog
MyScale Blog
Apple Machine Learning Research
Apple Machine Learning Research
L
LINUX DO - 最新话题
T
The Blog of Author Tim Ferriss
P
Proofpoint News Feed
宝玉的分享
宝玉的分享
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Visual Studio Blog
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园_首页
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
月光博客
月光博客
博客园 - 叶小钗
D
Docker
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
D
DataBreaches.Net
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog RSS Feed
量子位
美团技术团队
Vercel News
Vercel News
Y
Y Combinator Blog
IT之家
IT之家
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
SegmentFault 最新的问题
腾讯CDC
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
罗磊的独立博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
The Register - Security
The Register - Security
博客园 - 司徒正美
N
Netflix TechBlog - Medium
S
Schneier on Security
博客园 - 聂微东
U
Unit 42
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
Latest news
Latest news

Hacker News

Introducing Claude Opus 4.7 Qwen Studio The Future of Everything is Lies, I Guess: Where Do We Go From Here? GitHub - SeanFDZ/macmind: Single-layer transformer in HyperTalk for the classic Macintosh Show HN: Agent-cache – Multi-tier LLM/tool/session caching for Valkey and Redis Moving a large-scale metrics pipeline from StatsD to OpenTelemetry / Prometheus GitHub - Nightmare-Eclipse/RedSun: The Red Sun vulnerability repository GitHub - SethPyle376/hiraeth: Local AWS emulator focused on fast integration testing, with SQS support, SQLite-backed state, and a debug-friendly web UI. GitHub - macOS26/Agent: Any AI, replaces Claude Code, Cursor, OpenClaw. Over 18 LLM providers (Claude, OpenAI, Gemini, Ollama, Zai, HF, Qwen) wired into a native Mac app that writes code, builds Xcode projects, bumps versions, manages git, automates Safari, use AppleScript, JS or Accessibility, extend Agent! w/ MCP Servers, run tasks from your iPhone via Messages. YouTube now lets you turn off Shorts I Made a Terminal Pager Burgers | マクドナルド公式 Commands — HackerNews CLI documentation ChatGPT for Excel PiCore - Raspberry Pi Port of Tiny Core Linux Live Nation illegally monopolized ticketing market, jury finds Google Broke Its Promise to Me. Now ICE Has My Data. Founding Engineer at Adaptional | Y Combinator CRISPR takes important step toward silencing Down syndrome’s extra chromosome GitHub - saffron-health/libretto: The AI toolkit for building reliable browser automations US v. Heppner (S.D.N.Y. 2026) no attorney-client privilege for AI chats [pdf] Unexpected €54k billing spike in 13 hours: Firebase browser key without API restrictions used for Gemini requests Retrofitting JIT Compilers into C Interpreters IPv6 – Google The Accursèd Alphabetical Clock Cybersecurity Looks Like Proof of Work Now Fragments: April 14 Cal.com Goes Closed Source: Why AI Security Is Forcing Our Decision | Cal.com - Scheduling Software for Online Bookings Laravel raised money and now injects ads directly into your agent When moving fast, talking is the first thing to break Too much Discussion of the XOR swap trick – Heather Cafe Introduction to Spherical Harmonics for Graphics Programmers The Grand Line Building a Z-Machine in the worst possible language High-Level Rust: Getting 80% of the Benefits with 20% of the Pain GitHub - duguyue100/midnight-captain: Inspired by Midnight Commander, tailored to my taste. How to build a `git diff` driver · Jamie Tanna | Software Engineer Center for Responsible, Decentralized Intelligence at Berkeley The Local Universe’s Expansion Rate Is Clearer Than Ever, but Still Doesn’t Add Up - A new synthesis of astronomical measurements confirms a persistent mismatch that could point to physics beyond current models The air throughout our homes is infused with microplastics. But there are things you can do to breathe less of them The disturbing white paper Red Hat is trying to erase from the internet – OSnews The Future of Everything is Lies, I Guess: Annoyances ‘Abhorrent’: the inside story of the Polymarket gamblers betting millions on war Productive procrastination — Max van IJsselmuiden maps, territory and LMs 447 Terabytes per Square Centimetre at Zero Retention Energy: Non-Volatile Memory at the Atomic Scale on Fluorographane Show HN: Pardonned.com – A searchable database of US Pardons 20 Years on AWS and Never Not My Job The Seasons are Wrong Artemis II crew splashes down near San Diego after historic moon mission We gave an AI a 3 year retail lease in SF and asked it to make a profit | Andon Labs How a dancer with ALS used brainwaves to perform live On filing the corners off my MacBooks Installing every* Firefox extension OpenClaw’s memory is unreliable, and you don’t know when it will break Steve Blank Nowhere Is Safe Chimpanzees in Uganda locked in vicious 'civil war', say researchers watgo - a WebAssembly Toolkit for Go linux/Documentation/process/coding-assistants.rst at master · torvalds/linux GitHub - callumlocke/json-formatter: Makes JSON easy to read. Founding Product Engineer at Bild AI | Y Combinator A compelling title that is cryptic enough to get you to take action on it GitHub - Keychron/Keychron-Keyboards-Hardware-Design: Industrial design files for Keychron keyboards and mice. 100+ models with CAD assets in STEP, DXF, DWG, and PDF. Source-available, with commercial use allowed for original compatible accessories within the license terms. [ANNOUNCE] WireGuardNT v0.11 and WireGuard for Windows v0.6 Released 1D-Chess Helium Is Hard to Replace Cooperative Vectors Introduction | Evolve Keeping a Postgres queue healthy — PlanetScale Our response to the Axios developer tool compromise Do Americans read print books, e-books or audiobooks more? The Zettelkasten Method in Obsidian: A Practical Setup Guide Artemis II Is Competency Porn and We Are Starving For It WeakC4 Flight Viz — Cockpit View A Mexican surveillance giant you’ve never heard of is now watching the U.S. border Surelock: Deadlock-Free Mutexes for Rust RISC-V 101 – what is it and what does it mean for Canonical? | Ubuntu The Problem That Built an Industry How Much Linear Memory Access Is Enough? | Solidean Investigating Split Locks on x86-64 Simplest hash functions Sybilproof reputation mechanisms (2005) [pdf] What is a property? How Complex is my Code? Static code analysis in Kotlin — tools overview Toffoli gates are all you need PGLite evangelism dcmake: a new CMake debugger UI Clojure on Fennel part one: Persistent Data Structures Fragments: April 2 Python Release Python install manager 26.1 The Life and Death of the Book Review - Liberties Introducing Database Traffic Control — PlanetScale Bitcoin miners are losing $19,000 on every BTC produced as difficulty drops 7.8% God sleeps in the minerals Building slogbox Apple Silicon and Virtual Machines: Beating the 2 VM Limit Who was “Not Even Wrong” first? Pokemon Evolution Vs Darwinian Evolution The APL Programming Language Source Code
Also-rANS: Asymmetric Numeral Systems for entropy coding
2026-04-30 · via Hacker News

rANS is one of a family of entropy coding methods that we can use to compress a stream of symbols losslessly. For some set of symbols sSs \in S, w/ accompanying probabilities psp_s, Shannon’s source coding theorem tells us that symbol with probability psp_s carries exactly log2(1/ps)\log_2(1/p_s) bits of information. A symbol that shows up half the time costs 1 bit. One that shows up a quarter of the time costs 2 bits. One that shows up 3/8 of the time costs log2(8/3)1.415\log_2(8/3) \approx 1.415 bits.

Huffman coding can help us cleanly with the first two. But it uses fixed width symbols. The third symbol is going to end up taking 22 bits to decode. The result is that we can’t get perfect lossless compression.

rANS is one of a set of arithmetic coding methods that can achieve perfect compression, by not using fixed width symbols. Instead, the stream of bits is encoded into an integer, by a series of reversible arithmetic operations.

Encoding a sequence into an integer§

The code is a single integer, call it the state xx. Each symbol we encode transforms xx through some arithmetic operation. The operation has to be reversible, because the decoder needs to recover both the symbol and the previous state from the new one.

The specific operation rANS uses is:

x=xfsM+cs+(xmodfs)x' = \left\lfloor \frac{x}{f_s} \right\rfloor \cdot M + c_s + (x \bmod f_s)

where fsf_s is the frequency of symbol ss in our probability table, csc_s is its cumulative frequency (the sum of frequencies of all symbols that come before it in our enumeration), and MM is the total frequency sfs\sum_s f_s. For our alphabet, that’s:

Symbol   f_s   c_s
A        4     0
B        3     4
C        1     7

So M=8M = 8.

Let me walk through encoding the sequence A,B,CA, B, C starting from some seed state x=13x = 13. Pick 13 arbitrarily for now; we’ll talk about why the seed value matters later.

Encode AA (f=4f = 4, c=0c = 0):

x=1348+0+(13mod4)=38+0+1=25x' = \left\lfloor \frac{13}{4} \right\rfloor \cdot 8 + 0 + (13 \bmod 4) = 3 \cdot 8 + 0 + 1 = 25

Encode BB (f=3f = 3, c=4c = 4):

x=2538+4+(25mod3)=88+4+1=69x' = \left\lfloor \frac{25}{3} \right\rfloor \cdot 8 + 4 + (25 \bmod 3) = 8 \cdot 8 + 4 + 1 = 69

Encode CC (f=1f = 1, c=7c = 7):

x=6918+7+(69mod1)=698+7+0=559x' = \left\lfloor \frac{69}{1} \right\rfloor \cdot 8 + 7 + (69 \bmod 1) = 69 \cdot 8 + 7 + 0 = 559

The state walked 13256955913 \to 25 \to 69 \to 559. After encoding three symbols, our whole “code” is the single integer 559559. The entire message is packed into that number.

Now the payoff. Let’s check how much the state grew in bits. It started at log2(13)3.70\log_2(13) \approx 3.70 bits. It ended at log2(559)9.13\log_2(559) \approx 9.13 bits. We added 5.435.43 bits total. Shannon says our three symbols carry 1+1.415+3=5.4151 + 1.415 + 3 = 5.415 bits of information. The state grew by almost exactly that muchThe per-step growth wasn’t exactly 1, 1.415, 3 bits either. Encoding AA grew the state by log2(25/13)0.94\log_2(25/13) \approx 0.94 bits, less than Shannon’s 11 bit for AA. Encoding BB grew it by log2(69/25)1.47\log_2(69/25) \approx 1.47 bits, a hair over Shannon’s 1.4151.415. These individual wobbles are a quirk of encoding integer states. Each step rounds slightly up or down depending on where xx lands relative to fsf_s. The rANS guarantee is asymptotic, so over many symbols the wobbles average out and the per-symbol cost converges to the Shannon limit..

Importantly, we didn’t round anything to the nearest bit. Encoding BB grew the state by 1.471.47 bits. Fractional bits!

Where did they come from? The formula again:

x=xfsM+cs+(xmodfs)x' = \left\lfloor \frac{x}{f_s} \right\rfloor \cdot M + c_s + (x \bmod f_s)

To first order, xxMfs=x/P(s)x' \approx x \cdot \frac{M}{f_s} = x / P(s). So log2x\log_2 x' grows by approximately log2(1/P(s))\log_2(1/P(s)), which is the Shannon information content of ss.

One way to think of rANS encoding is as a change of base that smuggles in the symbol along the way. In base fsf_s, the number xx has last digit xmodfsx \bmod f_s and “rest” x/fs\lfloor x / f_s \rfloor. In base MM, the encoded xx' has the same rest, but the last digit is promoted from a digit in [0,fs)[0, f_s) to a digit in [0,M)[0, M), specifically cs+(xmodfs)c_s + (x \bmod f_s). That promotion is where the symbol is injected: the promoted digit lands inside symbol ss‘s range [cs,cs+fs)[c_s, c_s + f_s). The decoder, which we’ll build next, reads xmodMx' \bmod M, sees which range the value falls in, and recovers both the symbol and the remainder.

Decoding reverses it§

To decode, we invert the encoding. Given a state xx', recover the last-encoded symbol and the previous state in three steps:

  1. Read the low digit xmodMx' \bmod M.
  2. Find the symbol ss whose range contains it, i.e. csxmodM<cs+fsc_s \leq x' \bmod M < c_s + f_s.
  3. Reconstruct the previous state:

x=xMfs+(xmodMcs)x = \left\lfloor \frac{x'}{M} \right\rfloor \cdot f_s + (x' \bmod M - c_s)

Walking back from our encoded state x=559x' = 559:

Decode from x=559x = 559:

  • 559mod8=7559 \bmod 8 = 7, which lies in CC‘s range [7,8)[7, 8). Symbol is CC.
  • Previous state: 559/81+(77)=691+0=69\left\lfloor 559/8 \right\rfloor \cdot 1 + (7 - 7) = 69 \cdot 1 + 0 = 69.

Decode from x=69x = 69:

  • 69mod8=569 \bmod 8 = 5, which lies in BB‘s range [4,7)[4, 7). Symbol is BB.
  • Previous state: 69/83+(54)=83+1=25\left\lfloor 69/8 \right\rfloor \cdot 3 + (5 - 4) = 8 \cdot 3 + 1 = 25.

Decode from x=25x = 25:

  • 25mod8=125 \bmod 8 = 1, which lies in AA‘s range [0,4)[0, 4). Symbol is AA.
  • Previous state: 25/84+(10)=34+1=13\left\lfloor 25/8 \right\rfloor \cdot 4 + (1 - 0) = 3 \cdot 4 + 1 = 13.

The state walked 559692513559 \to 69 \to 25 \to 13, the mirror image of the encoding walk, and we’re back at the seed. The decoded symbols appeared in the order C,B,AC, B, A.

Note the order. We encoded A,B,CA, B, C but decoded C,B,AC, B, A. rANS is last-in-first-out. The encoder behaves like a stack, and the decoder pops from it. In practice this means real rANS encoders process their input message in reverse order, so that the decoder, running forward through the compressed state, produces symbols in the correct forward order.

Renormalization§

Until now, our compressed “code” has been a single integer xx'. That’s mathematically tidy but not directly implementable. For a long input, log2x\log_2 x' grows linearly with the message length, so xx' itself grows exponentially, and no fixed-width integer can hold it.

The fix is renormalization. The idea is we keep the state in a fixed range [L,bL)[L, bL) for some chosen LL and base bb. Common choices are b=2b = 2 for a bit-level compressed stream or b=256b = 256 for a byte-level one. Before encoding any symbol, check whether encoding would push the state above bLbL. If so, shift the low base-bb digits of xx out to an output stream, one at a time, until xx is small enough that encoding will leave the state inside [L,bL)[L, bL).

This emitted stream is the actual output of the encoding algorithm. Instead of one giant integer, we get a stream of bits or bytes spilled during encoding, plus a small residual state (always in [L,bL)[L, bL)) left over at the end. The compressed output is the concatenation of the two.

Decoding reverses the process. Starting from the residual state, decode a symbol via the formula from the previous section, which shrinks the state by a factor of about 1/P(s)1/P(s). If the state has dropped below LL, refill it by pulling digits from the stream back into the state as low digits, until the state is in [L,bL)[L, bL) again. We then just repeat until the stream is empty and the state matches the seed.

Putting it together§

Here is complete rANS encode and decode, in pseudocode. Pick a state range [L,bL)[L, bL), share the frequency table {(fs,cs)}\{(f_s, c_s)\} and the total MM between encoder and decoder, and that’s the whole scheme.

def encode(message, freq, M, L, b):
    x = L                                    # seed state
    stream = []
    for s in reversed(message):              # process LIFO
        f, c = freq[s]
        while M * x >= b * L * f:            # renormalize: spill low digit
            stream.append(x % b)
            x //= b
        x = (x // f) * M + c + (x % f)       # apply encode formula
    return x, stream                         # residual state + digits

def decode(x, stream, freq, M, L, b, n):
    slot_to_symbol = build_slot_table(freq)  # e.g. [A,A,A,A,B,B,B,C]
    message = []
    for _ in range(n):
        slot = x % M
        s = slot_to_symbol[slot]
        message.append(s)
        f, c = freq[s]
        x = (x // M) * f + slot - c          # apply decode formula
        while x < L and stream:              # renormalize: refill low digit
            x = x * b + stream.pop()
    return message

slot_to_symbol is a lookup table of size MM holding which symbol owns each of the MM slot positions. For our running alphabet with M=8M = 8, it is the list [A,A,A,A,B,B,B,C][A, A, A, A, B, B, B, C] This is an O(1)O(1) way of solving the problem of finding the correct range. You could also search for it..

The decode step is cheap. Per symbol it is one mod, one table lookup, one integer division, one multiply, one add, one subtract, and possibly a few digit-reads from the stream. No variable-length prefix code, no bit-by-bit decoding. Each symbol takes near-constant work, which is why rANS and its variants are popular in performance-sensitive compressors.

Encoding and decoding are mirror images. Encoding processes the message in reverse and pushes digits onto the stream. Decoding processes the stream in reverse (via pop) and produces the message in forward order. The whole scheme is LIFO throughout: in symbols, and in stream digits.

That is rANS. A single integer carries fractional bits of information per symbol, arithmetic operations encode and decode reversibly, and renormalization keeps the whole thing to a bounded state plus a digit stream.