[{"data":1,"prerenderedAt":799},["ShallowReactive",2],{"navigation-en":3,"page-\u002Fguide\u002Fperformance":78,"surround-\u002Fguide\u002Fperformance":794},[4,26,56],{"title":5,"path":6,"stem":7,"children":8},"Introduction","\u002Fguide","1.guide\u002F1.index",[9,10,14,18,22],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Getting Started","\u002Fguide\u002Fgetting-started","1.guide\u002F2.getting-started",{"title":15,"path":16,"stem":17},"Number Formatting","\u002Fguide\u002Fformat-tokens","1.guide\u002F3.format-tokens",{"title":19,"path":20,"stem":21},"Performance","\u002Fguide\u002Fperformance","1.guide\u002F4.performance",{"title":23,"path":24,"stem":25},"Caveats","\u002Fguide\u002Fcaveats","1.guide\u002F5.caveats",{"title":27,"path":28,"stem":29,"children":30},"API Overview","\u002Fapi","2.api\u002F0.index",[31,32,36,40,44,48,52],{"title":27,"path":28,"stem":29},{"title":33,"path":34,"stem":35},"calc()","\u002Fapi\u002Fcalc","2.api\u002F1.calc",{"title":37,"path":38,"stem":39},"fmt()","\u002Fapi\u002Ffmt","2.api\u002F2.fmt",{"title":41,"path":42,"stem":43},"Chain API","\u002Fapi\u002Fchain","2.api\u002F3.chain",{"title":45,"path":46,"stem":47},"Standalone Functions","\u002Fapi\u002Fstandalone","2.api\u002F4.standalone",{"title":49,"path":50,"stem":51},"Aggregation","\u002Fapi\u002Faggregate","2.api\u002F5.aggregate",{"title":53,"path":54,"stem":55},"Global Config","\u002Fapi\u002Fconfig","2.api\u002F6.config",{"title":57,"path":58,"stem":59,"children":60},"Examples Overview","\u002Fexamples","3.examples\u002F0.index",[61,62,66,70,74],{"title":57,"path":58,"stem":59},{"title":63,"path":64,"stem":65},"Precision Loss","\u002Fexamples\u002Fprecision-loss","3.examples\u002F1.precision-loss",{"title":67,"path":68,"stem":69},"E-commerce","\u002Fexamples\u002Fecommerce","3.examples\u002F2.ecommerce",{"title":71,"path":72,"stem":73},"Complex Expressions","\u002Fexamples\u002Fcomplex","3.examples\u002F3.complex",{"title":75,"path":76,"stem":77},"Currency Conversion","\u002Fexamples\u002Fcurrency","3.examples\u002F4.currency",{"id":79,"title":19,"body":80,"description":787,"extension":788,"meta":789,"navigation":791,"path":20,"seo":792,"stem":21,"__hash__":793},"content_en\u002F1.guide\u002F4.performance.md",{"type":81,"value":82,"toc":775},"minimark",[83,87,112,117,120,125,223,278,282,285,393,434,448,452,467,597,609,613,619,725,738,742],[84,85,19],"h1",{"id":86},"performance",[88,89,90,94,95,99,100,103,104,107,108,111],"p",{},[91,92,93],"code",{},"@wzo\u002Fcalc"," has ",[96,97,98],"strong",{},"zero runtime dependencies"," and the ESM bundle is ",[96,101,102],{},"~12 KB"," gzipped. All computation runs internally through BigInt.\nWhile it is slower than native floating-point (which is fast but ",[96,105,106],{},"wrong","), precision arithmetic still reaches ",[96,109,110],{},"millions of operations per second"," — more than enough for everyday use.",[113,114,116],"h2",{"id":115},"comparison-with-other-libraries","Comparison with other libraries",[88,118,119],{},"Measured throughput against popular precision libraries (ops\u002Fs, higher is better; values vary by machine and are meant to indicate order of magnitude):",[121,122,124],"h3",{"id":123},"single-step-operations","Single-step operations",[126,127,128,153],"table",{},[129,130,131],"thead",{},[132,133,134,139,144,147,150],"tr",{},[135,136,138],"th",{"align":137},"left","Operation",[135,140,142],{"align":141},"right",[91,143,93],{},[135,145,146],{"align":141},"decimal.js",[135,148,149],{"align":141},"mathjs",[135,151,152],{"align":141},"a-calc",[154,155,156,180,202],"tbody",{},[132,157,158,165,171,174,177],{},[159,160,161,162],"td",{"align":137},"Addition ",[91,163,164],{},"0.1 + 0.2",[159,166,167,170],{"align":141},[96,168,169],{},"9,090,000"," 🥇",[159,172,173],{"align":141},"2,920,000",[159,175,176],{"align":141},"2,040,000",[159,178,179],{"align":141},"431,000",[132,181,182,188,193,196,199],{},[159,183,184,185],{"align":137},"Multiplication ",[91,186,187],{},"1.1 * 2.2",[159,189,190,170],{"align":141},[96,191,192],{},"8,160,000",[159,194,195],{"align":141},"2,280,000",[159,197,198],{"align":141},"1,590,000",[159,200,201],{"align":141},"139,000",[132,203,204,210,213,218,220],{},[159,205,206,207],{"align":137},"Division ",[91,208,209],{},"1 \u002F 3",[159,211,212],{"align":141},"2,740,000",[159,214,215,170],{"align":141},[96,216,217],{},"3,240,000",[159,219,176],{"align":141},[159,221,222],{"align":141},"450,000",[224,225,226,248],"ul",{},[227,228,229,232,233,235,236,239,240,243,244,247],"li",{},[96,230,231],{},"Addition \u002F multiplication",": ",[91,234,93],{}," is fastest, roughly ",[96,237,238],{},"3–3.6× ahead of decimal.js",". These operations use a ",[96,241,242],{},"number integer-scaling fast path"," — when operands are within the ",[91,245,246],{},"2^53"," safe integer range and have ≤ 15 decimal places, integer arithmetic is used (close to native speed), falling back to BigInt only if overflow is possible. Scaling is done with integer × 10ᵏ, never floating-point multiplication, so there is no precision loss.",[227,249,250,253,254,257,258,261,262,265,266,269,270,273,274,277],{},[96,251,252],{},"Division",": decimal.js is still fastest (its base-1e7 long division is heavily optimized; also, we compute 50 ",[96,255,256],{},"decimal"," places while it computes 50 ",[96,259,260],{},"significant digits",", a slightly different workload). By borrowing its ideas of pre-stored constants and early termination when the remainder is zero — ",[96,263,264],{},"pre-caching powers of 10"," to avoid repeated large-integer construction and a ",[96,267,268],{},"fast path for exact division"," — we improved from ~1.7M\u002Fs to ",[96,271,272],{},"~2.74M\u002Fs",", narrowing the gap from 1.8× to ",[96,275,276],{},"1.18×",".",[121,279,281],{"id":280},"complex-expression-evaluation","Complex expression evaluation",[88,283,284],{},"Real-world workloads rarely involve single operations — they more often involve parentheses, discount\u002Fpromotion calculations, compound interest with repeated multiplication, or multiple divisions. The expressions below were cross-validated against mathjs (BigNumber 80-digit) and results match exactly; only throughput is compared (decimal.js has no expression parser and is excluded):",[126,286,287,304],{},[129,288,289],{},[132,290,291,294,298,300,302],{},[135,292,293],{"align":137},"Expression",[135,295,296],{"align":141},[91,297,93],{},[135,299,149],{"align":141},[135,301,152],{"align":141},[135,303,146],{"align":141},[154,305,306,328,350,371],{},[132,307,308,314,319,322,325],{},[159,309,310,313],{"align":137},[91,311,312],{},"1 + 2 * 2"," (simple)",[159,315,316,170],{"align":141},[96,317,318],{},"2,310,000",[159,320,321],{"align":141},"590,000",[159,323,324],{"align":141},"419,000",[159,326,327],{"align":141},"— (no expression parser)",[132,329,330,336,341,344,347],{},[159,331,332,333],{"align":137},"Discount ",[91,334,335],{},"(999.99*3 + 499.5*2 + 199.9*5)*0.85 - 200",[159,337,338,170],{"align":141},[96,339,340],{},"463,000",[159,342,343],{"align":141},"98,000",[159,345,346],{"align":141},"207,000",[159,348,349],{"align":141},"—",[132,351,352,358,363,366,369],{},[159,353,354,355],{"align":137},"Compound interest ",[91,356,357],{},"100000 * 1.004⁶ - 100000",[159,359,360,170],{"align":141},[96,361,362],{},"299,000",[159,364,365],{"align":141},"148,000",[159,367,368],{"align":141},"198,000",[159,370,349],{"align":141},[132,372,373,380,385,388,391],{},[159,374,375,376,379],{"align":137},"Multiple divisions ",[91,377,378],{},"1000\u002F3 + 2000\u002F7 + 3000\u002F11 + 4000\u002F13 + 5000\u002F17"," (repeating decimals)",[159,381,382],{"align":141},[96,383,384],{},"132,000",[159,386,387],{"align":141},"85,000",[159,389,390],{"align":141},"143,000 🥇",[159,392,349],{"align":141},[224,394,395,418,424],{},[227,396,397,232,400,402,403,406,407,410,411,406,414,417],{},[96,398,399],{},"Expressions dominated by addition\u002Fsubtraction\u002Fmultiplication",[91,401,93],{}," is fastest — roughly ",[96,404,405],{},"5.5× ahead of a-calc"," and ",[96,408,409],{},"3.9× ahead of mathjs"," for simple expressions; roughly ",[96,412,413],{},"2.2× ahead of a-calc",[96,415,416],{},"4.7× ahead of mathjs"," for discount calculations.",[227,419,420,423],{},[96,421,422],{},"Division-heavy expressions",": the advantage narrows to roughly on par with a-calc (results vary), while still ~1.6× ahead of mathjs — high-precision division must go through BigInt and cannot use the number fast path.",[227,425,426,427,429,430,433],{},"For single-step addition\u002Fsubtraction\u002Fmultiplication, ",[91,428,93],{}," is ",[96,431,432],{},"19–20× faster than a-calc",", which is also string-based.",[435,436,437],"blockquote",{},[88,438,439,440,443,444,447],{},"The comparison benchmark is at ",[91,441,442],{},"packages\u002Fmain\u002Ftests\u002Fcompare.bench.ts",". Run ",[91,445,446],{},"pnpm --filter @wzo\u002Fcalc exec vitest bench --run compare"," to reproduce (decimal.js \u002F mathjs are devDependencies for benchmarking only and are not included in the runtime bundle).",[113,449,451],{"id":450},"throughput-benchmarks","Throughput benchmarks",[88,453,454,455,458,459,466],{},"Results from ",[91,456,457],{},"pnpm --filter @wzo\u002Fcalc bench"," (using ",[460,461,465],"a",{"href":462,"rel":463},"https:\u002F\u002Fvitest.dev\u002Fguide\u002Ffeatures.html#benchmarking",[464],"nofollow","Vitest Bench","); values vary by machine and are meant to indicate order of magnitude:",[126,468,469,478],{},[129,470,471],{},[132,472,473,475],{},[135,474,138],{"align":137},[135,476,477],{"align":141},"Throughput (ops\u002Fs)",[154,479,480,490,500,510,521,531,542,552,563,573,583],{},[132,481,482,487],{},[159,483,484],{"align":137},[91,485,486],{},"addStr('0.1', '0.2')",[159,488,489],{"align":141},"~8,900,000",[132,491,492,497],{},[159,493,494],{"align":137},[91,495,496],{},"mul('1.1', '2.2')",[159,498,499],{"align":141},"~8,100,000",[132,501,502,507],{},[159,503,504],{"align":137},[91,505,506],{},"chainAdd(10).sub(3).mul(2)()",[159,508,509],{"align":141},"~7,100,000",[132,511,512,518],{},[159,513,514,517],{"align":137},[91,515,516],{},"add(0.1, 0.2)"," (→ number)",[159,519,520],{"align":141},"~4,700,000",[132,522,523,528],{},[159,524,525],{"align":137},[91,526,527],{},"fmt(n, { decimals: 2, thousands: true })",[159,529,530],{"align":141},"~2,900,000",[132,532,533,539],{},[159,534,535,538],{"align":137},[91,536,537],{},"div('1', '3')"," (50 places)",[159,540,541],{"align":141},"~2,630,000",[132,543,544,549],{},[159,545,546],{"align":137},[91,547,548],{},"calc('1 + 2 * 2')",[159,550,551],{"align":141},"~2,400,000",[132,553,554,560],{},[159,555,556,559],{"align":137},[91,557,558],{},"calc('9.9 * 3', { _fmt })"," (evaluate + format)",[159,561,562],{"align":141},"~2,080,000",[132,564,565,570],{},[159,566,567],{"align":137},[91,568,569],{},"fmt(n, { compact: 'zh' })",[159,571,572],{"align":141},"~630,000",[132,574,575,581],{},[159,576,577,580],{"align":137},[91,578,579],{},"calc('clamp(max(3, 5) * 2, 0, 100)')"," (math functions)",[159,582,572],{"align":141},[132,584,585,590],{},[159,586,587,588],{"align":137},"— Reference: native ",[91,589,164],{},[159,591,592,593,596],{"align":141},"~50,000,000 (but = ",[91,594,595],{},"0.30000000000000004",")",[435,598,599],{},[88,600,601,602,604,605,608],{},"Native floating-point is roughly 10–15× faster, but produces wrong results. ",[91,603,93],{}," trades that small speed difference for ",[96,606,607],{},"strict correctness"," — individual operations still run in microseconds.",[113,610,612],{"id":611},"correctness-comparison","Correctness comparison",[88,614,615,616,618],{},"This is where ",[91,617,93],{}," delivers its real value — native floating-point fails all of these classic cases:",[126,620,621,634],{},[129,622,623],{},[132,624,625,627,630],{},[135,626,293],{"align":137},[135,628,629],{"align":137},"Native JS",[135,631,632],{"align":137},[91,633,93],{},[154,635,636,653,670,687,708],{},[132,637,638,642,647],{},[159,639,640],{"align":137},[91,641,164],{},[159,643,644,646],{"align":137},[91,645,595],{}," ❌",[159,648,649,652],{"align":137},[91,650,651],{},"\"0.3\""," ✓",[132,654,655,660,665],{},[159,656,657],{"align":137},[91,658,659],{},"0.3 - 0.1",[159,661,662,646],{"align":137},[91,663,664],{},"0.19999999999999998",[159,666,667,652],{"align":137},[91,668,669],{},"\"0.2\"",[132,671,672,677,682],{},[159,673,674],{"align":137},[91,675,676],{},"0.1 * 0.2",[159,678,679,646],{"align":137},[91,680,681],{},"0.020000000000000004",[159,683,684,652],{"align":137},[91,685,686],{},"\"0.02\"",[132,688,689,694,699],{},[159,690,691],{"align":137},[91,692,693],{},"(1.005).toFixed(2)",[159,695,696,646],{"align":137},[91,697,698],{},"\"1.00\"",[159,700,701,704,705,596],{"align":137},[91,702,703],{},"\"1.01\""," ✓ (with ",[91,706,707],{},"rounding: 'round'",[132,709,710,715,720],{},[159,711,712],{"align":137},[91,713,714],{},"9007199254740993 + 0",[159,716,717,646],{"align":137},[91,718,719],{},"9007199254740992",[159,721,722,652],{"align":137},[91,723,724],{},"\"9007199254740993\"",[726,727,729],"callout",{"type":728},"info",[88,730,731,732,734,735,277],{},"Benchmarks are reproducible: run ",[91,733,457],{}," from the repository root. Test cases are in ",[91,736,737],{},"packages\u002Fmain\u002Ftests\u002Fperf.bench.ts",[113,739,741],{"id":740},"performance-tips","Performance tips",[224,743,744,759],{},[227,745,746,232,749,751,752,754,755,758],{},[96,747,748],{},"Pass strings for precision-sensitive values",[91,750,486],{}," is slightly faster than ",[91,753,516],{}," and skips the ",[91,756,757],{},"Number()"," conversion, making it safer too.",[227,760,761,232,764,767,768,771,772,277],{},[96,762,763],{},"Fewer formatting fields = faster",[91,765,766],{},"compact"," \u002F ",[91,769,770],{},"clamp"," and similar options are slightly heavier than plain ",[91,773,774],{},"decimals",{"title":776,"searchDepth":777,"depth":777,"links":778},"",2,[779,784,785,786],{"id":115,"depth":777,"text":116,"children":780},[781,783],{"id":123,"depth":782,"text":124},3,{"id":280,"depth":782,"text":281},{"id":450,"depth":777,"text":451},{"id":611,"depth":777,"text":612},{"id":740,"depth":777,"text":741},"Zero runtime dependencies, ~12KB gzip; precision arithmetic still reaches millions of operations per second.","md",{"icon":790},"i-lucide-gauge",true,{"title":19,"description":787},"A9-hYb5f56R5jk6mNSjV-HJMylvuyNUy6uBxMWq0pmU",[795,797],{"title":15,"path":16,"stem":17,"description":796,"children":-1},"Configure number formatting with the type-friendly IFormat object — thousands separators, percent, compact notation, and rounding all in one place.",{"title":23,"path":24,"stem":25,"description":798,"children":-1},"A few edge cases worth knowing before you start — error handling, precision pitfalls, and configuration scope.",1783414278789]