fractiondemo.gno
2.19 Kb · 67 lines
1// Package fractiondemo is a small gnoweb demo of the exact rational arithmetic
2// provided by the [p/moul/x/daily/fraction](/p/moul/x/daily/fraction/v0)
3// library: it shows thirds summing to exactly one, and a comparison that a
4// decimal detour would get wrong.
5//
6// It contains no arithmetic of its own. Stateless, so Render is deterministic.
7package fractiondemo
8
9import (
10 "strings"
11
12 "gno.land/p/moul/x/daily/fraction/v0"
13)
14
15// Render renders the demo for gnoweb.
16func Render(path string) string {
17 var b strings.Builder
18 b.WriteString("# Fractions\n\n")
19 b.WriteString("Exact rational arithmetic, demoing the ")
20 b.WriteString("[`p/moul/x/daily/fraction`](/p/moul/x/daily/fraction/v0) library.\n\n")
21
22 third, _ := fraction.New(1, 3)
23 sum, _ := third.Add(third)
24 sum, _ = sum.Add(third)
25
26 b.WriteString("## A third, three times\n\n")
27 b.WriteString("`1/3 + 1/3 + 1/3` = **")
28 b.WriteString(sum.String())
29 b.WriteString("**, exactly — not 0.9999…\n\n")
30 b.WriteString("As a decimal it is only ever an approximation: `")
31 b.WriteString(fraction.Decimal(third, 10))
32 b.WriteString("`\n")
33
34 half, _ := fraction.New(1, 2)
35 b.WriteString("\n## Arithmetic\n\n| expression | result |\n|---|---|\n")
36 add, _ := half.Add(third)
37 sub, _ := half.Sub(third)
38 mul, _ := half.Mul(third)
39 div, _ := half.Div(third)
40 row(&b, "1/2 + 1/3", add.String())
41 row(&b, "1/2 - 1/3", sub.String())
42 row(&b, "1/2 × 1/3", mul.String())
43 row(&b, "1/2 ÷ 1/3", div.String())
44
45 approx, _ := fraction.New(33333, 100000)
46 b.WriteString("\n## Exact comparison\n\n")
47 b.WriteString("`1/3` vs `33333/100000` — identical to five decimal places, ")
48 b.WriteString("yet the library still knows which is larger: **")
49 if third.Cmp(approx) > 0 {
50 b.WriteString("1/3 is greater")
51 } else {
52 b.WriteString("33333/100000 is greater or equal")
53 }
54 b.WriteString("**\n\n")
55 b.WriteString("> Comparison cross-multiplies, so it never takes a decimal detour. ")
56 b.WriteString("There are no floats here: on a chain, an answer that depends on ")
57 b.WriteString("rounding is a consensus bug.\n")
58 return b.String()
59}
60
61func row(b *strings.Builder, expr, res string) {
62 b.WriteString("| `")
63 b.WriteString(expr)
64 b.WriteString("` | `")
65 b.WriteString(res)
66 b.WriteString("` |\n")
67}