<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://blog.ashwork.net/programming</id>
    <title>Ash's Workshop Debrief Blog</title>
    <updated>2026-05-31T04:39:30.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://blog.ashwork.net/programming"/>
    <subtitle>Ash's Workshop Debrief Blog</subtitle>
    <icon>https://blog.ashwork.net/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[Why 0.1 + 0.2 = 0.30000000000000004]]></title>
        <id>https://blog.ashwork.net/programming/2026/05/31/precision-issues</id>
        <link href="https://blog.ashwork.net/programming/2026/05/31/precision-issues"/>
        <updated>2026-05-31T04:39:30.000Z</updated>
        <summary type="html"><![CDATA[How do you know whether two expressions are equivalent?]]></summary>
        <content type="html"><![CDATA[<p>How do you know whether two expressions are equivalent?</p>
<p>As humans, this can be a rather simple task: we apply the formulas we know to convert one expression to another. But for computers, they may not be aware of all the general nuances and complexities that come with math expressions. Therefore, many checkers typically choose the brute force approach: that is, plug in numbers and check whether the returned values are the same. Rather simplistic, but it gets the job done well in a number of cases.</p>
<p>Let's take a look at an example:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>f</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mfrac><mn>2</mn><mn>3</mn></mfrac><msup><mo stretchy="false">)</mo><mi>x</mi></msup></mrow><annotation encoding="application/x-tex">f_1(x)=(\frac23)^x
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>f</mi><mn>2</mn></msub><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mfrac><msup><mn>2</mn><mi>x</mi></msup><msup><mn>3</mn><mi>x</mi></msup></mfrac><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f_2(x)=(\frac{2^x}{3^x})
</annotation></semantics></math></span>
<p>Take a moment to convince yourself that <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>f</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>f</mi><mn>2</mn></msub><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f_1(x)=f_2(x)</annotation></semantics></math></span> due to the Power of a Quotient rule. Therefore if we were to create a new equation:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>f</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>−</mo><msub><mi>f</mi><mn>2</mn></msub><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">d(x)=f_1(x)-f_2(x)
</annotation></semantics></math></span>
<p>We should see that <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">d(x)=0</annotation></semantics></math></span> for all values of <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span>. So, when we look at a graph:</p>
<iframe src="https://www.desmos.com/calculator/csowgloafz?embed" width="100%" height="100%" style="border:1px solid #ccc"></iframe>
<p>...hm, well that's weird. The graph seems to stop arbitrarily at <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><mn>1024</mn></mrow><annotation encoding="application/x-tex">x=1024</annotation></semantics></math></span> while increasing exponentially around <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><mo>−</mo><mn>80</mn></mrow><annotation encoding="application/x-tex">x=-80</annotation></semantics></math></span>. And what's with that giant black bar at <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><mo>−</mo><mn>680</mn></mrow><annotation encoding="application/x-tex">x=-680</annotation></semantics></math></span> to <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><mo>−</mo><mn>650</mn></mrow><annotation encoding="application/x-tex">x=-650</annotation></semantics></math></span>?</p>
<p>Well, my dear readers, welcome to the wonderful world of floating point precision errors.</p>
<p>Hmm? What's a floating point precision error, you ask? Well, let me show you through a simple example.</p>
<p>Evaluate:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.1</mn><mo>+</mo><mn>0.2</mn></mrow><annotation encoding="application/x-tex">0.1+0.2
</annotation></semantics></math></span>
<p>Did you think the answer is <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.3</mn></mrow><annotation encoding="application/x-tex">0.3</annotation></semantics></math></span>? Well, I'm sorry to tell you that you're wrong. It's actually <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.30000000000000004</mn></mrow><annotation encoding="application/x-tex">0.30000000000000004</annotation></semantics></math></span>. Don't believe me? Open up a JavaScript console and try it yourself.</p>
<p>To understand why, let's look at the binary representations of these numbers. JavaScript stores decimal values as double-precision floating-point numbers following the <a href="https://en.wikipedia.org/wiki/IEEE_754" target="_blank" rel="noopener noreferrer" class="">IEEE 754 standard</a>. This means that a float is made up of 8 bytes, or 64 bits.</p>
<p>The IEEE 754 standard stores floating point numbers as a sort-of scientific notation with three parts: a 1 bit sign (positive or negative), a 52 bit fraction or significand, and a 11 bit exponent all in base 2.</p>
<p>We can get the bytes of a number with a neat little coding trick:</p>
<div class="expressive-code"><style>.expressive-code{font-family:var(--ec-uiFontFml);font-size:var(--ec-uiFontSize);font-weight:var(--ec-uiFontWg);line-height:var(--ec-uiLineHt);text-size-adjust:none;-webkit-text-size-adjust:none}.expressive-code *:not(:is(svg, svg *)){all:revert;box-sizing:border-box}.expressive-code pre{display:flex;margin:0;padding:0;border:var(--ec-brdWd) solid var(--ec-brdCol);border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));background:var(--ec-codeBg)}.expressive-code pre:focus-visible{outline:3px solid var(--ec-focusBrd);outline-offset:-3px}.expressive-code pre > code{all:unset;display:block;flex:1 0 100%;padding:var(--ec-codePadBlk) 0;color:var(--ec-codeFg);font-family:var(--ec-codeFontFml);font-size:var(--ec-codeFontSize);font-weight:var(--ec-codeFontWg);line-height:var(--ec-codeLineHt)}.expressive-code pre{overflow-x:auto}.expressive-code pre.wrap .ec-line .code{white-space:pre-wrap;overflow-wrap:break-word;min-width:min(20ch, var(--ecMaxLine, 20ch))}.expressive-code pre.wrap .ec-line .code span.indent{white-space:pre}.expressive-code pre::-webkit-scrollbar,.expressive-code pre::-webkit-scrollbar-track{background-color:inherit;border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));border-top-left-radius:0;border-top-right-radius:0}.expressive-code pre::-webkit-scrollbar-thumb{background-color:var(--ec-sbThumbCol);border:4px solid transparent;background-clip:content-box;border-radius:10px}.expressive-code pre::-webkit-scrollbar-thumb:hover{background-color:var(--ec-sbThumbHoverCol)}.expressive-code .ec-line{direction:ltr;unicode-bidi:isolate;display:grid;grid-template-areas:'gutter code';grid-template-columns:auto 1fr;position:relative}.expressive-code .ec-line .gutter{grid-area:gutter;color:var(--ec-gtrFg)}.expressive-code .ec-line .gutter > *{pointer-events:none;user-select:none;-webkit-user-select:none}.expressive-code .ec-line .gutter ~ .code{--ecLineBrdCol:var(--ec-gtrBrdCol)}.expressive-code .ec-line.highlight .gutter{color:var(--ec-gtrHlFg)}.expressive-code .ec-line .code{grid-area:code;position:relative;box-sizing:content-box;padding-inline-start:calc(var(--ecIndent, 0ch) + var(--ec-codePadInl) - var(--ecGtrBrdWd));padding-inline-end:var(--ec-codePadInl);text-indent:calc(var(--ecIndent, 0ch) * -1)}.expressive-code .ec-line .code::before,.expressive-code .ec-line .code::after,.expressive-code .ec-line .code :where(*){text-indent:0}.expressive-code .ec-line .code{--ecGtrBrdWd:var(--ec-gtrBrdWd);border-inline-start:var(--ecGtrBrdWd) solid var(--ecLineBrdCol, transparent)}.expressive-code .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}.expressive-code .ec-line.mark{--tmLineBgCol:var(--ec-tm-markBg)}.expressive-code .ec-line.mark .code{--ecLineBrdCol:var(--ec-tm-markBrdCol)}.expressive-code .ec-line.ins{--tmLineBgCol:var(--ec-tm-insBg);--tmLabel:var(--ec-tm-insDiffIndContent)}.expressive-code .ec-line.ins .code{--ecLineBrdCol:var(--ec-tm-insBrdCol)}.expressive-code .ec-line.ins .code::before{color:var(--ec-tm-insDiffIndCol)}.expressive-code .ec-line.del{--tmLineBgCol:var(--ec-tm-delBg);--tmLabel:var(--ec-tm-delDiffIndContent)}.expressive-code .ec-line.del .code{--ecLineBrdCol:var(--ec-tm-delBrdCol)}.expressive-code .ec-line.del .code::before{color:var(--ec-tm-delDiffIndCol)}.expressive-code .ec-line.mark,.expressive-code .ec-line.ins,.expressive-code .ec-line.del{background:var(--tmLineBgCol)}.expressive-code .ec-line.mark .code,.expressive-code .ec-line.ins .code,.expressive-code .ec-line.del .code{--ecGtrBrdWd:var(--ec-tm-lineMarkerAccentWd)}.expressive-code .ec-line.mark .code::before,.expressive-code .ec-line.ins .code::before,.expressive-code .ec-line.del .code::before{display:block;position:absolute;left:0;box-sizing:border-box;content:var(--tmLabel, ' ');padding-inline-start:var(--ec-tm-lineDiffIndMargLeft);text-align:center;white-space:pre}.expressive-code .ec-line.mark.tm-label .code::before,.expressive-code .ec-line.ins.tm-label .code::before,.expressive-code .ec-line.del.tm-label .code::before{background:var(--ecLineBrdCol);padding:0 calc(var(--ec-tm-lineMarkerLabelPadInl) + var(--ec-tm-lineMarkerAccentWd)) 0 var(--ec-tm-lineMarkerLabelPadInl);color:var(--ec-tm-lineMarkerLabelCol)}.expressive-code .ec-line mark{--tmInlineBgCol:var(--ec-tm-markBg);--tmInlineBrdCol:var(--ec-tm-markBrdCol)}.expressive-code .ec-line ins{--tmInlineBgCol:var(--ec-tm-insBg);--tmInlineBrdCol:var(--ec-tm-insBrdCol)}.expressive-code .ec-line del{--tmInlineBgCol:var(--ec-tm-delBg);--tmInlineBrdCol:var(--ec-tm-delBrdCol)}.expressive-code .ec-line mark,.expressive-code .ec-line ins,.expressive-code .ec-line del{all:unset;display:inline-block;position:relative;--tmBrdL:var(--ec-tm-inlMarkerBrdWd);--tmBrdR:var(--ec-tm-inlMarkerBrdWd);--tmRadL:var(--ec-tm-inlMarkerBrdRad);--tmRadR:var(--ec-tm-inlMarkerBrdRad);margin-inline:0.025rem;padding-inline:var(--ec-tm-inlMarkerPad);border-radius:var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);background:var(--tmInlineBgCol);background-clip:padding-box}.expressive-code .ec-line mark.open-start,.expressive-code .ec-line ins.open-start,.expressive-code .ec-line del.open-start{margin-inline-start:0;padding-inline-start:0;--tmBrdL:0px;--tmRadL:0}.expressive-code .ec-line mark.open-end,.expressive-code .ec-line ins.open-end,.expressive-code .ec-line del.open-end{margin-inline-end:0;padding-inline-end:0;--tmBrdR:0px;--tmRadR:0}.expressive-code .ec-line mark::before,.expressive-code .ec-line ins::before,.expressive-code .ec-line del::before{content:'';position:absolute;pointer-events:none;display:inline-block;inset:0;border-radius:var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);border:var(--ec-tm-inlMarkerBrdWd) solid var(--tmInlineBrdCol);border-inline-width:var(--tmBrdL) var(--tmBrdR)}.expressive-code .frame{all:unset;position:relative;display:block;--header-border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));--tab-border-radius:calc(var(--ec-frm-edTabBrdRad) + var(--ec-brdWd));--button-spacing:0.4rem;--code-background:var(--ec-frm-edBg);border-radius:var(--header-border-radius);box-shadow:var(--ec-frm-frameBoxShdCssVal)}.expressive-code .frame .header{display:none;z-index:1;position:relative;border-radius:var(--header-border-radius) var(--header-border-radius) 0 0}.expressive-code .frame.has-title pre,.expressive-code .frame.has-title code,.expressive-code .frame.is-terminal pre,.expressive-code .frame.is-terminal code{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.expressive-code .frame .title:empty:before{content:'\a0'}.expressive-code .frame.has-title:not(.is-terminal){--button-spacing:calc(1.9rem + 2 * (var(--ec-uiPadBlk) + var(--ec-frm-edActTabIndHt)))}.expressive-code .frame.has-title:not(.is-terminal) .title{position:relative;color:var(--ec-frm-edActTabFg);background:var(--ec-frm-edActTabBg);background-clip:padding-box;margin-block-start:var(--ec-frm-edTabsMargBlkStart);padding:calc(var(--ec-uiPadBlk) + var(--ec-frm-edActTabIndHt)) var(--ec-uiPadInl);border:var(--ec-brdWd) solid var(--ec-frm-edActTabBrdCol);border-radius:var(--tab-border-radius) var(--tab-border-radius) 0 0;border-bottom:none;overflow:hidden}.expressive-code .frame.has-title:not(.is-terminal) .title::after{content:'';position:absolute;pointer-events:none;inset:0;border-top:var(--ec-frm-edActTabIndHt) solid var(--ec-frm-edActTabIndTopCol);border-bottom:var(--ec-frm-edActTabIndHt) solid var(--ec-frm-edActTabIndBtmCol)}.expressive-code .frame.has-title:not(.is-terminal) .header{display:flex;background:linear-gradient(to top, var(--ec-frm-edTabBarBrdBtmCol) var(--ec-brdWd), transparent var(--ec-brdWd)),linear-gradient(var(--ec-frm-edTabBarBg), var(--ec-frm-edTabBarBg));background-repeat:no-repeat;padding-inline-start:var(--ec-frm-edTabsMargInlStart)}.expressive-code .frame.has-title:not(.is-terminal) .header::before{content:'';position:absolute;pointer-events:none;inset:0;border:var(--ec-brdWd) solid var(--ec-frm-edTabBarBrdCol);border-radius:inherit;border-bottom:none}.expressive-code .frame.is-terminal{--button-spacing:calc(1.9rem + var(--ec-brdWd) + 2 * var(--ec-uiPadBlk));--code-background:var(--ec-frm-trmBg)}.expressive-code .frame.is-terminal .header{display:flex;align-items:center;justify-content:center;padding-block:var(--ec-uiPadBlk);padding-block-end:calc(var(--ec-uiPadBlk) + var(--ec-brdWd));position:relative;font-weight:500;letter-spacing:0.025ch;color:var(--ec-frm-trmTtbFg);background:var(--ec-frm-trmTtbBg);border:var(--ec-brdWd) solid var(--ec-brdCol);border-bottom:none}.expressive-code .frame.is-terminal .header::before{content:'';position:absolute;pointer-events:none;left:var(--ec-uiPadInl);width:2.1rem;height:0.56rem;line-height:0;background-color:var(--ec-frm-trmTtbDotsFg);opacity:var(--ec-frm-trmTtbDotsOpa);-webkit-mask-image:var(--ec-frm-trmIcon);-webkit-mask-repeat:no-repeat;mask-image:var(--ec-frm-trmIcon);mask-repeat:no-repeat}.expressive-code .frame.is-terminal .header::after{content:'';position:absolute;pointer-events:none;inset:0;border-bottom:var(--ec-brdWd) solid var(--ec-frm-trmTtbBrdBtmCol)}.expressive-code .frame pre{background:var(--code-background)}.expressive-code .copy{display:flex;gap:0.25rem;flex-direction:row;position:absolute;inset-block-start:calc(var(--ec-brdWd) + var(--button-spacing));inset-inline-end:calc(var(--ec-brdWd) + var(--ec-uiPadInl) / 2)}@media (scripting: none){.expressive-code .copy{display:none}}.expressive-code .copy{direction:ltr;unicode-bidi:isolate}.expressive-code .copy button{position:relative;align-self:flex-end;margin:0;padding:0;border:none;border-radius:0.2rem;z-index:1;cursor:pointer;transition-property:opacity, background, border-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.25, 0.46, 0.45, 0.94);width:2.5rem;height:2.5rem;background:var(--code-background);opacity:0.75}.expressive-code .copy button div{position:absolute;inset:0;border-radius:inherit;background:var(--ec-frm-inlBtnBg);opacity:var(--ec-frm-inlBtnBgIdleOpa);transition-property:inherit;transition-duration:inherit;transition-timing-function:inherit}.expressive-code .copy button::before{content:'';position:absolute;pointer-events:none;inset:0;border-radius:inherit;border:var(--ec-brdWd) solid var(--ec-frm-inlBtnBrd);opacity:var(--ec-frm-inlBtnBrdOpa)}.expressive-code .copy button::after{content:'';position:absolute;pointer-events:none;inset:0;background-color:var(--ec-frm-inlBtnFg);-webkit-mask-image:var(--ec-frm-copyIcon);-webkit-mask-repeat:no-repeat;mask-image:var(--ec-frm-copyIcon);mask-repeat:no-repeat;margin:0.475rem;line-height:0}.expressive-code .copy button:hover,.expressive-code .copy button:focus:focus-visible{opacity:1}.expressive-code .copy button:hover div,.expressive-code .copy button:focus:focus-visible div{opacity:var(--ec-frm-inlBtnBgHoverOrFocusOpa)}.expressive-code .copy button:active{opacity:1}.expressive-code .copy button:active div{opacity:var(--ec-frm-inlBtnBgActOpa)}.expressive-code .copy .feedback{--tooltip-arrow-size:0.35rem;--tooltip-bg:var(--ec-frm-tooltipSuccessBg);color:var(--ec-frm-tooltipSuccessFg);pointer-events:none;user-select:none;-webkit-user-select:none;position:relative;align-self:center;background-color:var(--tooltip-bg);z-index:99;padding:0.125rem 0.75rem;border-radius:0.2rem;margin-inline-end:var(--tooltip-arrow-size);opacity:0;transition-property:opacity, transform;transition-duration:0.2s;transition-timing-function:ease-in-out;transform:translate3d(0, 0.25rem, 0)}.expressive-code .copy .feedback::after{content:'';position:absolute;pointer-events:none;top:calc(50% - var(--tooltip-arrow-size));inset-inline-end:calc(-2 * (var(--tooltip-arrow-size) - 0.5px));border:var(--tooltip-arrow-size) solid transparent;border-inline-start-color:var(--tooltip-bg)}.expressive-code .copy .feedback.show{opacity:1;transform:translate3d(0, 0, 0)}@media (hover: hover){.expressive-code{}.expressive-code .copy button{opacity:0;width:2rem;height:2rem}.expressive-code .frame:hover .copy button:not(:hover),.expressive-code .frame:focus-within :focus-visible ~ .copy button:not(:hover),.expressive-code .frame .copy .feedback.show ~ button:not(:hover){opacity:0.75}}.expressive-code :nth-child(1 of .ec-line) .code{padding-inline-end:calc(2rem + var(--ec-codePadInl))}:root,:root:not([data-theme='github-dark']) .expressive-code[data-theme='github-dark']{--ec-brdRad:0.3rem;--ec-brdWd:1.5px;--ec-brdCol:#1b1f23;--ec-codeFontFml:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace;--ec-codeFontSize:0.85rem;--ec-codeFontWg:400;--ec-codeLineHt:1.65;--ec-codePadBlk:1rem;--ec-codePadInl:1.35rem;--ec-codeBg:#24292e;--ec-codeFg:#e1e4e8;--ec-codeSelBg:#3392ff44;--ec-gtrFg:#727980;--ec-gtrBrdCol:#72798033;--ec-gtrBrdWd:1.5px;--ec-gtrHlFg:#e1e4e896;--ec-uiFontFml:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji';--ec-uiFontSize:0.9rem;--ec-uiFontWg:400;--ec-uiLineHt:1.65;--ec-uiPadBlk:0.25rem;--ec-uiPadInl:1rem;--ec-uiSelBg:#39414a;--ec-uiSelFg:#e1e4e8;--ec-focusBrd:#005cc5;--ec-sbThumbCol:#6a737d33;--ec-sbThumbHoverCol:#6a737dd1;--ec-tm-lineMarkerAccentMarg:0rem;--ec-tm-lineMarkerAccentWd:0.15rem;--ec-tm-lineMarkerLabelPadInl:0.2rem;--ec-tm-lineMarkerLabelCol:white;--ec-tm-lineDiffIndMargLeft:0.3rem;--ec-tm-inlMarkerBrdWd:1.5px;--ec-tm-inlMarkerBrdRad:0.2rem;--ec-tm-inlMarkerPad:0.15rem;--ec-tm-insDiffIndContent:'+';--ec-tm-delDiffIndContent:'-';--ec-tm-markBg:#264a8980;--ec-tm-markBrdCol:#5570b3d0;--ec-tm-insBg:#26561c80;--ec-tm-insBrdCol:#4e7e41d0;--ec-tm-insDiffIndCol:#7eb070d0;--ec-tm-delBg:#81322b80;--ec-tm-delBrdCol:#ae594fd0;--ec-tm-delDiffIndCol:#e68a7ed0;--ec-frm-shdCol:#0000005b;--ec-frm-frameBoxShdCssVal:0.1rem 0.1rem 0.2rem #0000005b;--ec-frm-edActTabBg:#24292e;--ec-frm-edActTabFg:#e1e4e8;--ec-frm-edActTabBrdCol:transparent;--ec-frm-edActTabIndHt:1.5px;--ec-frm-edActTabIndTopCol:#f9826c;--ec-frm-edActTabIndBtmCol:#24292e;--ec-frm-edTabsMargInlStart:0;--ec-frm-edTabsMargBlkStart:0;--ec-frm-edTabBrdRad:0.3rem;--ec-frm-edTabBarBg:#1f2428;--ec-frm-edTabBarBrdCol:#1b1f23;--ec-frm-edTabBarBrdBtmCol:#1b1f23;--ec-frm-edBg:#24292e;--ec-frm-trmTtbFg:#e1e4e8;--ec-frm-trmTtbDotsFg:#e1e4e8;--ec-frm-trmTtbDotsOpa:0.15;--ec-frm-trmTtbBg:#24292e;--ec-frm-trmTtbBrdBtmCol:#1b1f23;--ec-frm-trmBg:#1f2428;--ec-frm-inlBtnFg:#e1e4e8;--ec-frm-inlBtnBg:#e1e4e8;--ec-frm-inlBtnBgIdleOpa:0;--ec-frm-inlBtnBgHoverOrFocusOpa:0.2;--ec-frm-inlBtnBgActOpa:0.3;--ec-frm-inlBtnBrd:#e1e4e8;--ec-frm-inlBtnBrdOpa:0.4;--ec-frm-tooltipSuccessBg:#228739;--ec-frm-tooltipSuccessFg:white;--ec-frm-copyIcon:url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2024%2024'%20fill%3D'none'%20stroke%3D'black'%20stroke-width%3D'1.75'%3E%3Cpath%20d%3D'M3%2019a2%202%200%200%201-1-2V2a2%202%200%200%201%201-1h13a2%202%200%200%201%202%201'%2F%3E%3Crect%20x%3D'6'%20y%3D'5'%20width%3D'16'%20height%3D'18'%20rx%3D'1.5'%20ry%3D'1.5'%2F%3E%3C%2Fsvg%3E");--ec-frm-trmIcon:url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2060%2016'%20preserveAspectRatio%3D'xMidYMid%20meet'%3E%3Ccircle%20cx%3D'8'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'30'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'52'%20cy%3D'8'%20r%3D'8'%2F%3E%3C%2Fsvg%3E")}.expressive-code .ec-line :where(span[style^='--']:not([class])),:root:not([data-theme='github-dark']) .expressive-code[data-theme='github-dark'] .ec-line :where(span[style^='--']:not([class])){color:var(--0, inherit);background-color:var(--0bg, transparent);font-style:var(--0fs, inherit);font-weight:var(--0fw, inherit);text-decoration:var(--0td, inherit)}@media (prefers-color-scheme: light){:root:not([data-theme='github-dark']){--ec-brdCol:#e1e4e8;--ec-codeBg:#fff;--ec-codeFg:#24292e;--ec-codeSelBg:#0366d625;--ec-gtrFg:#1b1f2381;--ec-gtrBrdCol:#1b1f2333;--ec-gtrHlFg:#24292eab;--ec-uiSelBg:#e2e5e9;--ec-uiSelFg:#2f363d;--ec-focusBrd:#2188ff;--ec-sbThumbCol:#959da533;--ec-sbThumbHoverCol:#959da5eb;--ec-tm-markBg:#9fb6ff80;--ec-tm-insBg:#94c68480;--ec-tm-insDiffIndCol:#3a692fd0;--ec-tm-delBg:#fea09280;--ec-tm-delDiffIndCol:#97453dd0;--ec-frm-shdCol:#00000028;--ec-frm-frameBoxShdCssVal:0.1rem 0.1rem 0.2rem #00000028;--ec-frm-edActTabBg:#fff;--ec-frm-edActTabFg:#2f363d;--ec-frm-edActTabIndBtmCol:#fff;--ec-frm-edTabBarBg:#f6f8fa;--ec-frm-edTabBarBrdCol:#e1e4e8;--ec-frm-edTabBarBrdBtmCol:#e1e4e8;--ec-frm-edBg:#fff;--ec-frm-trmTtbFg:#2f363d;--ec-frm-trmTtbDotsFg:#2f363d;--ec-frm-trmTtbBg:#fff;--ec-frm-trmTtbBrdBtmCol:#e1e4e8;--ec-frm-trmBg:#f6f8fa;--ec-frm-inlBtnFg:#24292e;--ec-frm-inlBtnBg:#24292e;--ec-frm-inlBtnBrd:#24292e;--ec-frm-tooltipSuccessBg:#208638}:root:not([data-theme='github-dark']) .expressive-code .ec-line :where(span[style^='--']:not([class])){color:var(--1, inherit);background-color:var(--1bg, transparent);font-style:var(--1fs, inherit);font-weight:var(--1fw, inherit);text-decoration:var(--1td, inherit)}}:root[data-theme='github-light'] .expressive-code:not([data-theme='github-dark']),.expressive-code[data-theme='github-light']{--ec-brdCol:#e1e4e8;--ec-codeBg:#fff;--ec-codeFg:#24292e;--ec-codeSelBg:#0366d625;--ec-gtrFg:#1b1f2381;--ec-gtrBrdCol:#1b1f2333;--ec-gtrHlFg:#24292eab;--ec-uiSelBg:#e2e5e9;--ec-uiSelFg:#2f363d;--ec-focusBrd:#2188ff;--ec-sbThumbCol:#959da533;--ec-sbThumbHoverCol:#959da5eb;--ec-tm-markBg:#9fb6ff80;--ec-tm-insBg:#94c68480;--ec-tm-insDiffIndCol:#3a692fd0;--ec-tm-delBg:#fea09280;--ec-tm-delDiffIndCol:#97453dd0;--ec-frm-shdCol:#00000028;--ec-frm-frameBoxShdCssVal:0.1rem 0.1rem 0.2rem #00000028;--ec-frm-edActTabBg:#fff;--ec-frm-edActTabFg:#2f363d;--ec-frm-edActTabIndBtmCol:#fff;--ec-frm-edTabBarBg:#f6f8fa;--ec-frm-edTabBarBrdCol:#e1e4e8;--ec-frm-edTabBarBrdBtmCol:#e1e4e8;--ec-frm-edBg:#fff;--ec-frm-trmTtbFg:#2f363d;--ec-frm-trmTtbDotsFg:#2f363d;--ec-frm-trmTtbBg:#fff;--ec-frm-trmTtbBrdBtmCol:#e1e4e8;--ec-frm-trmBg:#f6f8fa;--ec-frm-inlBtnFg:#24292e;--ec-frm-inlBtnBg:#24292e;--ec-frm-inlBtnBrd:#24292e;--ec-frm-tooltipSuccessBg:#208638}:root[data-theme='github-light'] .expressive-code:not([data-theme='github-dark']) .ec-line :where(span[style^='--']:not([class])),.expressive-code[data-theme='github-light'] .ec-line :where(span[style^='--']:not([class])){color:var(--1, inherit);background-color:var(--1bg, transparent);font-style:var(--1fs, inherit);font-weight:var(--1fw, inherit);text-decoration:var(--1td, inherit)}</style><script type="module">try{(()=>{var e=window.requestIdleCallback||(e=>setTimeout(e,1)),t=window.cancelIdleCallback||clearTimeout;function r(e,t){e.querySelectorAll?.(".expressive-code pre > code").forEach(e=>{let r=e.parentElement;r&&t.observe(r)})}var o=function(r){let o,n,a=new Set;return new ResizeObserver(i=>{i.forEach(e=>a.add(e.target)),o&&clearTimeout(o),n&&t(n),o=setTimeout(()=>{n&&t(n),n=e(()=>{a.forEach(e=>r(e)),a.clear()})},250)})}(function(e){if(!e)return;let t=null!==e.getAttribute("tabindex"),r=e.scrollWidth>e.clientWidth;r&&!t?(e.setAttribute("tabindex","0"),e.setAttribute("role","region")):!r&&t&&(e.removeAttribute("tabindex"),e.removeAttribute("role"))});r(document,o),new MutationObserver(e=>e.forEach(e=>e.addedNodes.forEach(e=>{r(e,o)}))).observe(document.body,{childList:!0,subtree:!0}),document.addEventListener("astro:page-load",()=>{r(document,o)})})()}catch(e){console.error("[EC] tabindex-js-module failed:",e)}</script><script type="module">try{(()=>{async function e(e){let t=e.currentTarget,o=t.dataset,n=!1,a=o.code.replace(/\u007f/g,"\n");try{await navigator.clipboard.writeText(a),n=!0}catch{n=function(e){let t=document.createElement("pre");Object.assign(t.style,{opacity:"0",pointerEvents:"none",position:"absolute",overflow:"hidden",left:"0",top:"0",width:"20px",height:"20px",webkitUserSelect:"auto",userSelect:"all"}),t.ariaHidden="true",t.textContent=e,document.body.appendChild(t);let o=document.createRange();o.selectNode(t);let n=getSelection();if(!n)return!1;n.removeAllRanges(),n.addRange(o);let a=!1;try{a=document.execCommand("copy")}finally{n.removeAllRanges(),document.body.removeChild(t)}return a}(a)}if(!n||t.parentNode?.querySelector(".feedback"))return;let d=t.parentNode?.querySelector("[aria-live]"),r=document.createElement("div");r.classList.add("feedback"),r.append(o.copied),d.append(r),r.offsetWidth,requestAnimationFrame(()=>r?.classList.add("show"));let c=()=>!r||r.classList.remove("show"),i=()=>{!r||parseFloat(getComputedStyle(r).opacity)>0||(r.remove(),r=void 0)};setTimeout(c,1500),setTimeout(i,2500),t.addEventListener("blur",c),r.addEventListener("transitioncancel",i),r.addEventListener("transitionend",i)}function t(t){t.querySelectorAll?.(".expressive-code .copy button").forEach(t=>t.addEventListener("click",e))}t(document),new MutationObserver(e=>e.forEach(e=>e.addedNodes.forEach(e=>{t(e)}))).observe(document.body,{childList:!0,subtree:!0}),document.addEventListener("astro:page-load",()=>{t(document)})})()}catch(e){console.error("[EC] copy-js-module failed:",e)}</script><figure class="frame"><figcaption class="header"></figcaption><pre tabindex="0" class="codeBlockStandalone_MEMb thin-scrollbar codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><code class="codeBlockLines_e6Vv"><div class="ec-line"><div class="code"><span style="--0:#F97583;--1:#BF3441">function</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">floatToBinaryString</span><span style="--0:#E1E4E8;--1:#24292E">(</span><span style="--0:#FFAB70;--1:#AE4B07">value</span><span style="--0:#E1E4E8;--1:#24292E">) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">var</span><span style="--0:#E1E4E8;--1:#24292E"> output </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#9ECBFF;--1:#032F62">''</span><span style="--0:#E1E4E8;--1:#24292E">;</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#99A0A6;--1:#616972">// Get the bytes in reverse order</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">for</span><span style="--0:#E1E4E8;--1:#24292E"> (</span><span style="--0:#F97583;--1:#BF3441">const</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">part</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">of</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">new</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">Uint8Array</span><span style="--0:#E1E4E8;--1:#24292E">(</span><span style="--0:#F97583;--1:#BF3441">new</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">Float64Array</span><span style="--0:#E1E4E8;--1:#24292E">([value]).buffer, </span><span style="--0:#79B8FF;--1:#005CC5">0</span><span style="--0:#E1E4E8;--1:#24292E">, </span><span style="--0:#79B8FF;--1:#005CC5">8</span><span style="--0:#E1E4E8;--1:#24292E">)) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#99A0A6;--1:#616972">// Convert to string</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#F97583;--1:#BF3441">var</span><span style="--0:#E1E4E8;--1:#24292E"> partString </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> (part </span><span style="--0:#F97583;--1:#BF3441">&gt;&gt;&gt;</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">0</span><span style="--0:#E1E4E8;--1:#24292E">).</span><span style="--0:#B392F0;--1:#6F42C1">toString</span><span style="--0:#E1E4E8;--1:#24292E">(</span><span style="--0:#79B8FF;--1:#005CC5">2</span><span style="--0:#E1E4E8;--1:#24292E">);</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#99A0A6;--1:#616972">// Pad any missing zeros</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#F97583;--1:#BF3441">while</span><span style="--0:#E1E4E8;--1:#24292E"> (partString.</span><span style="--0:#79B8FF;--1:#005CC5">length</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">&lt;</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">8</span><span style="--0:#E1E4E8;--1:#24292E">) partString </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#9ECBFF;--1:#032F62">'0'</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">+</span><span style="--0:#E1E4E8;--1:#24292E"> partString;</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#99A0A6;--1:#616972">// Prefix to place in proper order</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">        </span></span><span style="--0:#E1E4E8;--1:#24292E">output </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> partString </span><span style="--0:#F97583;--1:#BF3441">+</span><span style="--0:#E1E4E8;--1:#24292E"> output;</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">    </span></span><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">return</span><span style="--0:#E1E4E8;--1:#24292E"> output;</span></div></div><div class="ec-line"><div class="code"><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="function floatToBinaryString(value) {    var output = '';    // Get the bytes in reverse order    for (const part of new Uint8Array(new Float64Array([value]).buffer, 0, 8)) {        // Convert to string        var partString = (part >>> 0).toString(2);        // Pad any missing zeros        while (partString.length < 8) partString = '0' + partString;        // Prefix to place in proper order        output = partString + output;    }    return output;}"><div></div></button></div></figure></div>
<p>Using this, the binary representations of our two numbers are:</p>
<div class="expressive-code"><figure class="frame"><figcaption class="header"></figcaption><pre tabindex="0" class="codeBlockStandalone_MEMb thin-scrollbar codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><code class="codeBlockLines_e6Vv"><div class="ec-line"><div class="code"><span style="--0:#99A0A6;--1:#616972">// Values are displayed in the correct order</span></div></div><div class="ec-line"><div class="code"><span style="--0:#99A0A6;--1:#616972">// In the form '&lt;Sign&gt; &lt;Exponent&gt; &lt;Fraction&gt;'</span></div></div><div class="ec-line"><div class="code"><span style="--0:#79B8FF;--1:#005CC5">0.1</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">0</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">01111111011</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">1001100110011001100110011001100110011001100110011010</span></div></div><div class="ec-line"><div class="code"><span style="--0:#79B8FF;--1:#005CC5">0.2</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">0</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">01111111100</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">1001100110011001100110011001100110011001100110011010</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="// Values are displayed in the correct order// In the form '<Sign> <Exponent> <Fraction>'0.1 = 0 01111111011 10011001100110011001100110011001100110011001100110100.2 = 0 01111111100 1001100110011001100110011001100110011001100110011010"><div></div></button></div></figure></div>
<p>Now at a glance, you can tell something is weird, especially with that fraction part. It shouldn't be that complicated to store <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.1</mn></mrow><annotation encoding="application/x-tex">0.1</annotation></semantics></math></span> or <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.2</mn></mrow><annotation encoding="application/x-tex">0.2</annotation></semantics></math></span> in base 2, right?</p>
<p>Why don't we try evaluating these binary values manually then?</p>
<p>The sign is rather straight forward (0 if positive and 1 if negative). The same goes for the fraction: the sum of all <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mrow><mo>−</mo><mi>n</mi></mrow></msup></mrow><annotation encoding="application/x-tex">2^{-n}</annotation></semantics></math></span> that have a 1, where <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span> is the bit number starting from 1, plus 1. The exponent, on the other hand, is calculated differently to allow for negative values. This is done by performing the standard base 2 to base 10 conversion, then subtracting <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mrow><mi>k</mi><mo>−</mo><mn>1</mn></mrow></msup><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">2^{k-1}-1</annotation></semantics></math></span>, where <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span> is the number of bits in the exponent (in this case <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>=</mo><mn>11</mn></mrow><annotation encoding="application/x-tex">k=11</annotation></semantics></math></span>). Then all of these parts are multiplied together.</p>
<p>That was probably not explained that well, so let me show you the code:</p>
<div class="expressive-code"><figure class="frame"><figcaption class="header"></figcaption><pre tabindex="0" class="codeBlockStandalone_MEMb thin-scrollbar codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><code class="codeBlockLines_e6Vv"><div class="ec-line"><div class="code"><span style="--0:#99A0A6;--1:#616972">// Outputs the sign</span></div></div><div class="ec-line"><div class="code"><span style="--0:#F97583;--1:#BF3441">function</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">binaryStringToSign</span><span style="--0:#E1E4E8;--1:#24292E">(</span><span style="--0:#FFAB70;--1:#AE4B07">value</span><span style="--0:#E1E4E8;--1:#24292E">) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#99A0A6;--1:#616972">// Gets the sign value from the first part</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">return</span><span style="--0:#E1E4E8;--1:#24292E"> value[</span><span style="--0:#79B8FF;--1:#005CC5">0</span><span style="--0:#E1E4E8;--1:#24292E">] </span><span style="--0:#F97583;--1:#BF3441">===</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#9ECBFF;--1:#032F62">'0'</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">?</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">1</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">:</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">-</span><span style="--0:#79B8FF;--1:#005CC5">1</span><span style="--0:#E1E4E8;--1:#24292E">;</span></div></div><div class="ec-line"><div class="code"><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div><div class="ec-line"><div class="code">
</div></div><div class="ec-line"><div class="code"><span style="--0:#99A0A6;--1:#616972">// Outputs the 2^n exponent</span></div></div><div class="ec-line"><div class="code"><span style="--0:#F97583;--1:#BF3441">function</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">binaryStringToExponent</span><span style="--0:#E1E4E8;--1:#24292E">(</span><span style="--0:#FFAB70;--1:#AE4B07">value</span><span style="--0:#E1E4E8;--1:#24292E">) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">var</span><span style="--0:#E1E4E8;--1:#24292E"> output </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">0</span><span style="--0:#E1E4E8;--1:#24292E">;</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#99A0A6;--1:#616972">// Compute initial exponent</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">for</span><span style="--0:#E1E4E8;--1:#24292E"> (</span><span style="--0:#F97583;--1:#BF3441">var</span><span style="--0:#E1E4E8;--1:#24292E"> i </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">0</span><span style="--0:#E1E4E8;--1:#24292E">; i </span><span style="--0:#F97583;--1:#BF3441">&lt;</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">11</span><span style="--0:#E1E4E8;--1:#24292E">; i</span><span style="--0:#F97583;--1:#BF3441">++</span><span style="--0:#E1E4E8;--1:#24292E">) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#F97583;--1:#BF3441">const</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">bit</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">parseInt</span><span style="--0:#E1E4E8;--1:#24292E">(value[i </span><span style="--0:#F97583;--1:#BF3441">+</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">1</span><span style="--0:#E1E4E8;--1:#24292E">]);</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">        </span></span><span style="--0:#E1E4E8;--1:#24292E">output </span><span style="--0:#F97583;--1:#BF3441">+=</span><span style="--0:#E1E4E8;--1:#24292E"> bit </span><span style="--0:#F97583;--1:#BF3441">*</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">2</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">**</span><span style="--0:#E1E4E8;--1:#24292E"> (</span><span style="--0:#79B8FF;--1:#005CC5">11</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">-</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">1</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">-</span><span style="--0:#E1E4E8;--1:#24292E"> i);</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">    </span></span><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#99A0A6;--1:#616972">// Apply bias</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">    </span></span><span style="--0:#E1E4E8;--1:#24292E">output </span><span style="--0:#F97583;--1:#BF3441">-=</span><span style="--0:#E1E4E8;--1:#24292E"> (</span><span style="--0:#79B8FF;--1:#005CC5">2</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">**</span><span style="--0:#E1E4E8;--1:#24292E"> (</span><span style="--0:#79B8FF;--1:#005CC5">11</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">-</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">1</span><span style="--0:#E1E4E8;--1:#24292E">)) </span><span style="--0:#F97583;--1:#BF3441">-</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">1</span><span style="--0:#E1E4E8;--1:#24292E">;</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#99A0A6;--1:#616972">// Return exponent to raise '2' to</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">return</span><span style="--0:#E1E4E8;--1:#24292E"> output;</span></div></div><div class="ec-line"><div class="code"><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div><div class="ec-line"><div class="code">
</div></div><div class="ec-line"><div class="code"><span style="--0:#99A0A6;--1:#616972">// Outputs the 2^n exponents to sum together and add 1</span></div></div><div class="ec-line"><div class="code"><span style="--0:#F97583;--1:#BF3441">function</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">binaryStringToFractionParts</span><span style="--0:#E1E4E8;--1:#24292E">(</span><span style="--0:#FFAB70;--1:#AE4B07">value</span><span style="--0:#E1E4E8;--1:#24292E">) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">const</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">output</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> [];</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#99A0A6;--1:#616972">// Compute fraction parts</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">for</span><span style="--0:#E1E4E8;--1:#24292E"> (</span><span style="--0:#F97583;--1:#BF3441">var</span><span style="--0:#E1E4E8;--1:#24292E"> i </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">0</span><span style="--0:#E1E4E8;--1:#24292E">; i </span><span style="--0:#F97583;--1:#BF3441">&lt;</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">52</span><span style="--0:#E1E4E8;--1:#24292E">; i</span><span style="--0:#F97583;--1:#BF3441">++</span><span style="--0:#E1E4E8;--1:#24292E">) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#F97583;--1:#BF3441">const</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">bit</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">parseInt</span><span style="--0:#E1E4E8;--1:#24292E">(value[i </span><span style="--0:#F97583;--1:#BF3441">+</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">12</span><span style="--0:#E1E4E8;--1:#24292E">]);</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#F97583;--1:#BF3441">if</span><span style="--0:#E1E4E8;--1:#24292E"> (bit </span><span style="--0:#F97583;--1:#BF3441">===</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">1</span><span style="--0:#E1E4E8;--1:#24292E">) output.</span><span style="--0:#B392F0;--1:#6F42C1">push</span><span style="--0:#E1E4E8;--1:#24292E">((</span><span style="--0:#F97583;--1:#BF3441">-</span><span style="--0:#E1E4E8;--1:#24292E">(i </span><span style="--0:#F97583;--1:#BF3441">+</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">1</span><span style="--0:#E1E4E8;--1:#24292E">)));</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">    </span></span><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">return</span><span style="--0:#E1E4E8;--1:#24292E"> output;</span></div></div><div class="ec-line"><div class="code"><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="// Outputs the signfunction binaryStringToSign(value) {    // Gets the sign value from the first part    return value[0] === '0' ? 1 : -1;}// Outputs the 2^n exponentfunction binaryStringToExponent(value) {    var output = 0;    // Compute initial exponent    for (var i = 0; i < 11; i++) {        const bit = parseInt(value[i + 1]);        output += bit * 2 ** (11 - 1 - i);    }    // Apply bias    output -= (2 ** (11 - 1)) - 1;    // Return exponent to raise '2' to    return output;}// Outputs the 2^n exponents to sum together and add 1function binaryStringToFractionParts(value) {    const output = [];    // Compute fraction parts    for (var i = 0; i < 52; i++) {        const bit = parseInt(value[i + 12]);        if (bit === 1) output.push((-(i + 1)));    }    return output;}"><div></div></button></div></figure></div>
<p>With all this, we can add up the values in our accurate calculator of choice (e.g., Wolfram Alpha):</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>1</mn><mo>∗</mo><msup><mn>2</mn><mrow><mo>−</mo><mn>4</mn></mrow></msup><mo>∗</mo><mo stretchy="false">(</mo><mn>1</mn><mo>+</mo><mn>0.600000000000000088817841970012523233890533447265625</mn><mo stretchy="false">)</mo><mo>=</mo></mrow><annotation encoding="application/x-tex">1 * 2^{-4} * (1 + 0.600000000000000088817841970012523233890533447265625) =
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.1000000000000000055511151231257827021181583404541015625</mn></mrow><annotation encoding="application/x-tex">0.1000000000000000055511151231257827021181583404541015625
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>1</mn><mo>∗</mo><msup><mn>2</mn><mrow><mo>−</mo><mn>3</mn></mrow></msup><mo>∗</mo><mo stretchy="false">(</mo><mn>1</mn><mo>+</mo><mn>0.600000000000000088817841970012523233890533447265625</mn><mo stretchy="false">)</mo><mo>=</mo></mrow><annotation encoding="application/x-tex">1 * 2^{-3} * (1 + 0.600000000000000088817841970012523233890533447265625) =
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.200000000000000011102230246251565404236316680908203125</mn></mrow><annotation encoding="application/x-tex">0.200000000000000011102230246251565404236316680908203125
</annotation></semantics></math></span>
<p>Well, that's pretty much <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.1</mn></mrow><annotation encoding="application/x-tex">0.1</annotation></semantics></math></span> and <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.2</mn></mrow><annotation encoding="application/x-tex">0.2</annotation></semantics></math></span>, but it's not exactly those values. It's just a really accurate approximation, leaving some room for precision error.</p>
<p>But wait. Adding those two numbers together, we get:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.1000000000000000055511151231257827021181583404541015625</mn><mo>+</mo></mrow><annotation encoding="application/x-tex">0.1000000000000000055511151231257827021181583404541015625 +
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.200000000000000011102230246251565404236316680908203125</mn><mo>=</mo></mrow><annotation encoding="application/x-tex">0.200000000000000011102230246251565404236316680908203125 =
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.3000000000000000166533453693773481063544750213623046875</mn></mrow><annotation encoding="application/x-tex">0.3000000000000000166533453693773481063544750213623046875
</annotation></semantics></math></span>
<p>Which is definitely not <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.30000000000000004</mn></mrow><annotation encoding="application/x-tex">0.30000000000000004</annotation></semantics></math></span>. Though, surprisingly enough, if we put that number into the JavaScript console, it does equal that value. So, there's even more precision bugs to work out.</p>
<p>Adding two floating-point numbers together require the exponents to be the same before adding the fraction component. First, let's convert this to a more convenient form to perform the operations on:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.1</mn><mo>=</mo><mn>1.1001100110011001100110011001100110011001100110011010</mn><mo>∗</mo><msup><mn>2</mn><mn>01111111011</mn></msup></mrow><annotation encoding="application/x-tex">0.1 = 1.1001100110011001100110011001100110011001100110011010 * 2^{01111111011}
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.2</mn><mo>=</mo><mn>1.1001100110011001100110011001100110011001100110011010</mn><mo>∗</mo><msup><mn>2</mn><mn>01111111100</mn></msup></mrow><annotation encoding="application/x-tex">0.2 = 1.1001100110011001100110011001100110011001100110011010 * 2^{01111111100}
</annotation></semantics></math></span>
<p>In this case, the exponent for <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.1</mn></mrow><annotation encoding="application/x-tex">0.1</annotation></semantics></math></span> is <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>01111111011</mn></mrow><annotation encoding="application/x-tex">01111111011</annotation></semantics></math></span> while it's <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>01111111100</mn></mrow><annotation encoding="application/x-tex">01111111100</annotation></semantics></math></span> for <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.2</mn></mrow><annotation encoding="application/x-tex">0.2</annotation></semantics></math></span>. Well, that's easy enough to deal with. We can increase the exponent for <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.1</mn></mrow><annotation encoding="application/x-tex">0.1</annotation></semantics></math></span> by 1 by shifting the fraction component 1 to the left.</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.1</mn><mo>=</mo><mn>0.1100110011001100110011001100110011001100110011001101</mn><mo>∗</mo><msup><mn>2</mn><mn>01111111100</mn></msup></mrow><annotation encoding="application/x-tex">0.1 = 0.1100110011001100110011001100110011001100110011001101 * 2^{01111111100}
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.2</mn><mo>=</mo><mn>1.1001100110011001100110011001100110011001100110011010</mn><mo>∗</mo><msup><mn>2</mn><mn>01111111100</mn></msup></mrow><annotation encoding="application/x-tex">0.2 = 1.1001100110011001100110011001100110011001100110011010 * 2^{01111111100}
</annotation></semantics></math></span>
<p>Now all that's left to do is add the two fraction parts together:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.1100110011001100110011001100110011001100110011001101</mn><mo>+</mo></mrow><annotation encoding="application/x-tex">0.1100110011001100110011001100110011001100110011001101 +
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>1.1001100110011001100110011001100110011001100110011010</mn><mo>=</mo></mrow><annotation encoding="application/x-tex">1.1001100110011001100110011001100110011001100110011010 =
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>10.0110011001100110011001100110011001100110011001100111</mn></mrow><annotation encoding="application/x-tex">10.0110011001100110011001100110011001100110011001100111
</annotation></semantics></math></span>
<p>Which we can rewrite as:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.3</mn><mo>=</mo><mn>10.0110011001100110011001100110011001100110011001100111</mn><mo>∗</mo><msup><mn>2</mn><mn>01111111100</mn></msup></mrow><annotation encoding="application/x-tex">0.3 = 10.0110011001100110011001100110011001100110011001100111 * 2^{01111111100}
</annotation></semantics></math></span>
<p>Shift to match proper scientific notation:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.3</mn><mo>=</mo><mn>1.00110011001100110011001100110011001100110011001100111</mn><mo>∗</mo><msup><mn>2</mn><mn>01111111101</mn></msup></mrow><annotation encoding="application/x-tex">0.3 = 1.00110011001100110011001100110011001100110011001100111 * 2^{01111111101}
</annotation></semantics></math></span>
<p>And round since there are now 53 bits representing the exponent. We round up if the 52nd bit is 1, and down if 0:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.3</mn><mo>=</mo><mn>1.0011001100110011001100110011001100110011001100110100</mn><mo>∗</mo><msup><mn>2</mn><mn>01111111101</mn></msup></mrow><annotation encoding="application/x-tex">0.3 = 1.0011001100110011001100110011001100110011001100110100 * 2^{01111111101}
</annotation></semantics></math></span>
<p>Which leaves us with the final number:</p>
<div class="expressive-code"><figure class="frame"><figcaption class="header"></figcaption><pre tabindex="0" class="codeBlockStandalone_MEMb thin-scrollbar codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><code class="codeBlockLines_e6Vv"><div class="ec-line"><div class="code"><span style="--0:#79B8FF;--1:#005CC5">0.3</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">0</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">01111111101</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">0011001100110011001100110011001100110011001100110100</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="0.3 = 0 01111111101 0011001100110011001100110011001100110011001100110100"><div></div></button></div></figure></div>
<p>And sure enough, evaluating the floating-point precisely gives us:</p>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>1</mn><mo>∗</mo><msup><mn>2</mn><mrow><mo>−</mo><mn>2</mn></mrow></msup><mo>∗</mo><mo stretchy="false">(</mo><mn>1</mn><mo>+</mo><mn>0.20000000000000017763568394002504646778106689453125</mn><mo stretchy="false">)</mo><mo>=</mo></mrow><annotation encoding="application/x-tex">1 * 2^{-2} * (1 + 0.20000000000000017763568394002504646778106689453125) =
</annotation></semantics></math></span>
<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>0.3000000000000000444089209850062616169452667236328125</mn></mrow><annotation encoding="application/x-tex">0.3000000000000000444089209850062616169452667236328125
</annotation></semantics></math></span>
<p>Where we can now see that pesky <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>4</mn><mo>∗</mo><msup><mn>10</mn><mrow><mo>−</mo><mn>17</mn></mrow></msup></mrow><annotation encoding="application/x-tex">4*10^{-17}</annotation></semantics></math></span> rounding error. It's all a game of approximation math. And with those precision issues, <span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mfrac><mn>2</mn><mn>3</mn></mfrac><msup><mo stretchy="false">)</mo><mi>x</mi></msup><mo>−</mo><mo stretchy="false">(</mo><mfrac><msup><mn>2</mn><mi>x</mi></msup><msup><mn>3</mn><mi>x</mi></msup></mfrac><mo stretchy="false">)</mo><mo mathvariant="normal">≠</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">(\frac23)^{x}-(\frac{2^x}{3^x})\neq0</annotation></semantics></math></span>.</p>
<p>However, that graph hold a lot more math limitations than you think. But that's a story for next week.</p>]]></content>
        <author>
            <name>ChampionAsh5357</name>
            <uri>https://github.com/ChampionAsh5357</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Determining Java's Max Array Allocation Size]]></title>
        <id>https://blog.ashwork.net/programming/2026/05/17/array-allocation-limit</id>
        <link href="https://blog.ashwork.net/programming/2026/05/17/array-allocation-limit"/>
        <updated>2026-05-17T18:53:30.000Z</updated>
        <summary type="html"><![CDATA[For those unfamiliar, the Minecraft modding community just released a patch on May 11th, 2026 for a Memory Allocation with Excessive Size Value exploit when decoding a network packet.]]></summary>
        <content type="html"><![CDATA[<p>For those unfamiliar, the Minecraft modding community just released a patch on May 11th, 2026 for a <a href="https://cwe.mitre.org/data/definitions/789.html" target="_blank" rel="noopener noreferrer" class="">Memory Allocation with Excessive Size Value</a> exploit when decoding a network packet.</p>
<p>I was the one responsible for implementing the mitigation strategy and writing the <a href="https://neoforged.net/news/mitigating-vulnerabilities-network/" target="_blank" rel="noopener noreferrer" class="">blog post</a> for the NeoForged team. It was quite fun to research and learn some new things during the process.</p>
<p>However, this blog post has nothing to do with that.</p>
<p>During the review phase of the post, the original reporter of the exploit <a href="https://github.com/pau101" target="_blank" rel="noopener noreferrer" class="">Paul</a> mentioned that trying to allocate an array with <code>Integer.MAX_VALUE</code> will <a href="https://github.com/neoforged/websites/pull/100#discussion_r3253303333" target="_blank" rel="noopener noreferrer" class="">likely fail before any memory is allocated</a>. This actually comes from a comment in <a href="https://github.com/openjdk/jdk/blob/22b46872d0d647c9ef9f4414b4685afa8313926d/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java#L842-L854" target="_blank" rel="noopener noreferrer" class=""><code>ArraysSupport</code></a> that states:</p>
<div class="expressive-code"><style>.expressive-code{font-family:var(--ec-uiFontFml);font-size:var(--ec-uiFontSize);font-weight:var(--ec-uiFontWg);line-height:var(--ec-uiLineHt);text-size-adjust:none;-webkit-text-size-adjust:none}.expressive-code *:not(:is(svg, svg *)){all:revert;box-sizing:border-box}.expressive-code pre{display:flex;margin:0;padding:0;border:var(--ec-brdWd) solid var(--ec-brdCol);border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));background:var(--ec-codeBg)}.expressive-code pre:focus-visible{outline:3px solid var(--ec-focusBrd);outline-offset:-3px}.expressive-code pre > code{all:unset;display:block;flex:1 0 100%;padding:var(--ec-codePadBlk) 0;color:var(--ec-codeFg);font-family:var(--ec-codeFontFml);font-size:var(--ec-codeFontSize);font-weight:var(--ec-codeFontWg);line-height:var(--ec-codeLineHt)}.expressive-code pre{overflow-x:auto}.expressive-code pre.wrap .ec-line .code{white-space:pre-wrap;overflow-wrap:break-word;min-width:min(20ch, var(--ecMaxLine, 20ch))}.expressive-code pre.wrap .ec-line .code span.indent{white-space:pre}.expressive-code pre::-webkit-scrollbar,.expressive-code pre::-webkit-scrollbar-track{background-color:inherit;border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));border-top-left-radius:0;border-top-right-radius:0}.expressive-code pre::-webkit-scrollbar-thumb{background-color:var(--ec-sbThumbCol);border:4px solid transparent;background-clip:content-box;border-radius:10px}.expressive-code pre::-webkit-scrollbar-thumb:hover{background-color:var(--ec-sbThumbHoverCol)}.expressive-code .ec-line{direction:ltr;unicode-bidi:isolate;display:grid;grid-template-areas:'gutter code';grid-template-columns:auto 1fr;position:relative}.expressive-code .ec-line .gutter{grid-area:gutter;color:var(--ec-gtrFg)}.expressive-code .ec-line .gutter > *{pointer-events:none;user-select:none;-webkit-user-select:none}.expressive-code .ec-line .gutter ~ .code{--ecLineBrdCol:var(--ec-gtrBrdCol)}.expressive-code .ec-line.highlight .gutter{color:var(--ec-gtrHlFg)}.expressive-code .ec-line .code{grid-area:code;position:relative;box-sizing:content-box;padding-inline-start:calc(var(--ecIndent, 0ch) + var(--ec-codePadInl) - var(--ecGtrBrdWd));padding-inline-end:var(--ec-codePadInl);text-indent:calc(var(--ecIndent, 0ch) * -1)}.expressive-code .ec-line .code::before,.expressive-code .ec-line .code::after,.expressive-code .ec-line .code :where(*){text-indent:0}.expressive-code .ec-line .code{--ecGtrBrdWd:var(--ec-gtrBrdWd);border-inline-start:var(--ecGtrBrdWd) solid var(--ecLineBrdCol, transparent)}.expressive-code .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}.expressive-code .ec-line.mark{--tmLineBgCol:var(--ec-tm-markBg)}.expressive-code .ec-line.mark .code{--ecLineBrdCol:var(--ec-tm-markBrdCol)}.expressive-code .ec-line.ins{--tmLineBgCol:var(--ec-tm-insBg);--tmLabel:var(--ec-tm-insDiffIndContent)}.expressive-code .ec-line.ins .code{--ecLineBrdCol:var(--ec-tm-insBrdCol)}.expressive-code .ec-line.ins .code::before{color:var(--ec-tm-insDiffIndCol)}.expressive-code .ec-line.del{--tmLineBgCol:var(--ec-tm-delBg);--tmLabel:var(--ec-tm-delDiffIndContent)}.expressive-code .ec-line.del .code{--ecLineBrdCol:var(--ec-tm-delBrdCol)}.expressive-code .ec-line.del .code::before{color:var(--ec-tm-delDiffIndCol)}.expressive-code .ec-line.mark,.expressive-code .ec-line.ins,.expressive-code .ec-line.del{background:var(--tmLineBgCol)}.expressive-code .ec-line.mark .code,.expressive-code .ec-line.ins .code,.expressive-code .ec-line.del .code{--ecGtrBrdWd:var(--ec-tm-lineMarkerAccentWd)}.expressive-code .ec-line.mark .code::before,.expressive-code .ec-line.ins .code::before,.expressive-code .ec-line.del .code::before{display:block;position:absolute;left:0;box-sizing:border-box;content:var(--tmLabel, ' ');padding-inline-start:var(--ec-tm-lineDiffIndMargLeft);text-align:center;white-space:pre}.expressive-code .ec-line.mark.tm-label .code::before,.expressive-code .ec-line.ins.tm-label .code::before,.expressive-code .ec-line.del.tm-label .code::before{background:var(--ecLineBrdCol);padding:0 calc(var(--ec-tm-lineMarkerLabelPadInl) + var(--ec-tm-lineMarkerAccentWd)) 0 var(--ec-tm-lineMarkerLabelPadInl);color:var(--ec-tm-lineMarkerLabelCol)}.expressive-code .ec-line mark{--tmInlineBgCol:var(--ec-tm-markBg);--tmInlineBrdCol:var(--ec-tm-markBrdCol)}.expressive-code .ec-line ins{--tmInlineBgCol:var(--ec-tm-insBg);--tmInlineBrdCol:var(--ec-tm-insBrdCol)}.expressive-code .ec-line del{--tmInlineBgCol:var(--ec-tm-delBg);--tmInlineBrdCol:var(--ec-tm-delBrdCol)}.expressive-code .ec-line mark,.expressive-code .ec-line ins,.expressive-code .ec-line del{all:unset;display:inline-block;position:relative;--tmBrdL:var(--ec-tm-inlMarkerBrdWd);--tmBrdR:var(--ec-tm-inlMarkerBrdWd);--tmRadL:var(--ec-tm-inlMarkerBrdRad);--tmRadR:var(--ec-tm-inlMarkerBrdRad);margin-inline:0.025rem;padding-inline:var(--ec-tm-inlMarkerPad);border-radius:var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);background:var(--tmInlineBgCol);background-clip:padding-box}.expressive-code .ec-line mark.open-start,.expressive-code .ec-line ins.open-start,.expressive-code .ec-line del.open-start{margin-inline-start:0;padding-inline-start:0;--tmBrdL:0px;--tmRadL:0}.expressive-code .ec-line mark.open-end,.expressive-code .ec-line ins.open-end,.expressive-code .ec-line del.open-end{margin-inline-end:0;padding-inline-end:0;--tmBrdR:0px;--tmRadR:0}.expressive-code .ec-line mark::before,.expressive-code .ec-line ins::before,.expressive-code .ec-line del::before{content:'';position:absolute;pointer-events:none;display:inline-block;inset:0;border-radius:var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);border:var(--ec-tm-inlMarkerBrdWd) solid var(--tmInlineBrdCol);border-inline-width:var(--tmBrdL) var(--tmBrdR)}.expressive-code .frame{all:unset;position:relative;display:block;--header-border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));--tab-border-radius:calc(var(--ec-frm-edTabBrdRad) + var(--ec-brdWd));--button-spacing:0.4rem;--code-background:var(--ec-frm-edBg);border-radius:var(--header-border-radius);box-shadow:var(--ec-frm-frameBoxShdCssVal)}.expressive-code .frame .header{display:none;z-index:1;position:relative;border-radius:var(--header-border-radius) var(--header-border-radius) 0 0}.expressive-code .frame.has-title pre,.expressive-code .frame.has-title code,.expressive-code .frame.is-terminal pre,.expressive-code .frame.is-terminal code{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.expressive-code .frame .title:empty:before{content:'\a0'}.expressive-code .frame.has-title:not(.is-terminal){--button-spacing:calc(1.9rem + 2 * (var(--ec-uiPadBlk) + var(--ec-frm-edActTabIndHt)))}.expressive-code .frame.has-title:not(.is-terminal) .title{position:relative;color:var(--ec-frm-edActTabFg);background:var(--ec-frm-edActTabBg);background-clip:padding-box;margin-block-start:var(--ec-frm-edTabsMargBlkStart);padding:calc(var(--ec-uiPadBlk) + var(--ec-frm-edActTabIndHt)) var(--ec-uiPadInl);border:var(--ec-brdWd) solid var(--ec-frm-edActTabBrdCol);border-radius:var(--tab-border-radius) var(--tab-border-radius) 0 0;border-bottom:none;overflow:hidden}.expressive-code .frame.has-title:not(.is-terminal) .title::after{content:'';position:absolute;pointer-events:none;inset:0;border-top:var(--ec-frm-edActTabIndHt) solid var(--ec-frm-edActTabIndTopCol);border-bottom:var(--ec-frm-edActTabIndHt) solid var(--ec-frm-edActTabIndBtmCol)}.expressive-code .frame.has-title:not(.is-terminal) .header{display:flex;background:linear-gradient(to top, var(--ec-frm-edTabBarBrdBtmCol) var(--ec-brdWd), transparent var(--ec-brdWd)),linear-gradient(var(--ec-frm-edTabBarBg), var(--ec-frm-edTabBarBg));background-repeat:no-repeat;padding-inline-start:var(--ec-frm-edTabsMargInlStart)}.expressive-code .frame.has-title:not(.is-terminal) .header::before{content:'';position:absolute;pointer-events:none;inset:0;border:var(--ec-brdWd) solid var(--ec-frm-edTabBarBrdCol);border-radius:inherit;border-bottom:none}.expressive-code .frame.is-terminal{--button-spacing:calc(1.9rem + var(--ec-brdWd) + 2 * var(--ec-uiPadBlk));--code-background:var(--ec-frm-trmBg)}.expressive-code .frame.is-terminal .header{display:flex;align-items:center;justify-content:center;padding-block:var(--ec-uiPadBlk);padding-block-end:calc(var(--ec-uiPadBlk) + var(--ec-brdWd));position:relative;font-weight:500;letter-spacing:0.025ch;color:var(--ec-frm-trmTtbFg);background:var(--ec-frm-trmTtbBg);border:var(--ec-brdWd) solid var(--ec-brdCol);border-bottom:none}.expressive-code .frame.is-terminal .header::before{content:'';position:absolute;pointer-events:none;left:var(--ec-uiPadInl);width:2.1rem;height:0.56rem;line-height:0;background-color:var(--ec-frm-trmTtbDotsFg);opacity:var(--ec-frm-trmTtbDotsOpa);-webkit-mask-image:var(--ec-frm-trmIcon);-webkit-mask-repeat:no-repeat;mask-image:var(--ec-frm-trmIcon);mask-repeat:no-repeat}.expressive-code .frame.is-terminal .header::after{content:'';position:absolute;pointer-events:none;inset:0;border-bottom:var(--ec-brdWd) solid var(--ec-frm-trmTtbBrdBtmCol)}.expressive-code .frame pre{background:var(--code-background)}.expressive-code .copy{display:flex;gap:0.25rem;flex-direction:row;position:absolute;inset-block-start:calc(var(--ec-brdWd) + var(--button-spacing));inset-inline-end:calc(var(--ec-brdWd) + var(--ec-uiPadInl) / 2)}@media (scripting: none){.expressive-code .copy{display:none}}.expressive-code .copy{direction:ltr;unicode-bidi:isolate}.expressive-code .copy button{position:relative;align-self:flex-end;margin:0;padding:0;border:none;border-radius:0.2rem;z-index:1;cursor:pointer;transition-property:opacity, background, border-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.25, 0.46, 0.45, 0.94);width:2.5rem;height:2.5rem;background:var(--code-background);opacity:0.75}.expressive-code .copy button div{position:absolute;inset:0;border-radius:inherit;background:var(--ec-frm-inlBtnBg);opacity:var(--ec-frm-inlBtnBgIdleOpa);transition-property:inherit;transition-duration:inherit;transition-timing-function:inherit}.expressive-code .copy button::before{content:'';position:absolute;pointer-events:none;inset:0;border-radius:inherit;border:var(--ec-brdWd) solid var(--ec-frm-inlBtnBrd);opacity:var(--ec-frm-inlBtnBrdOpa)}.expressive-code .copy button::after{content:'';position:absolute;pointer-events:none;inset:0;background-color:var(--ec-frm-inlBtnFg);-webkit-mask-image:var(--ec-frm-copyIcon);-webkit-mask-repeat:no-repeat;mask-image:var(--ec-frm-copyIcon);mask-repeat:no-repeat;margin:0.475rem;line-height:0}.expressive-code .copy button:hover,.expressive-code .copy button:focus:focus-visible{opacity:1}.expressive-code .copy button:hover div,.expressive-code .copy button:focus:focus-visible div{opacity:var(--ec-frm-inlBtnBgHoverOrFocusOpa)}.expressive-code .copy button:active{opacity:1}.expressive-code .copy button:active div{opacity:var(--ec-frm-inlBtnBgActOpa)}.expressive-code .copy .feedback{--tooltip-arrow-size:0.35rem;--tooltip-bg:var(--ec-frm-tooltipSuccessBg);color:var(--ec-frm-tooltipSuccessFg);pointer-events:none;user-select:none;-webkit-user-select:none;position:relative;align-self:center;background-color:var(--tooltip-bg);z-index:99;padding:0.125rem 0.75rem;border-radius:0.2rem;margin-inline-end:var(--tooltip-arrow-size);opacity:0;transition-property:opacity, transform;transition-duration:0.2s;transition-timing-function:ease-in-out;transform:translate3d(0, 0.25rem, 0)}.expressive-code .copy .feedback::after{content:'';position:absolute;pointer-events:none;top:calc(50% - var(--tooltip-arrow-size));inset-inline-end:calc(-2 * (var(--tooltip-arrow-size) - 0.5px));border:var(--tooltip-arrow-size) solid transparent;border-inline-start-color:var(--tooltip-bg)}.expressive-code .copy .feedback.show{opacity:1;transform:translate3d(0, 0, 0)}@media (hover: hover){.expressive-code{}.expressive-code .copy button{opacity:0;width:2rem;height:2rem}.expressive-code .frame:hover .copy button:not(:hover),.expressive-code .frame:focus-within :focus-visible ~ .copy button:not(:hover),.expressive-code .frame .copy .feedback.show ~ button:not(:hover){opacity:0.75}}.expressive-code :nth-child(1 of .ec-line) .code{padding-inline-end:calc(2rem + var(--ec-codePadInl))}:root,:root:not([data-theme='github-dark']) .expressive-code[data-theme='github-dark']{--ec-brdRad:0.3rem;--ec-brdWd:1.5px;--ec-brdCol:#1b1f23;--ec-codeFontFml:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace;--ec-codeFontSize:0.85rem;--ec-codeFontWg:400;--ec-codeLineHt:1.65;--ec-codePadBlk:1rem;--ec-codePadInl:1.35rem;--ec-codeBg:#24292e;--ec-codeFg:#e1e4e8;--ec-codeSelBg:#3392ff44;--ec-gtrFg:#727980;--ec-gtrBrdCol:#72798033;--ec-gtrBrdWd:1.5px;--ec-gtrHlFg:#e1e4e896;--ec-uiFontFml:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji';--ec-uiFontSize:0.9rem;--ec-uiFontWg:400;--ec-uiLineHt:1.65;--ec-uiPadBlk:0.25rem;--ec-uiPadInl:1rem;--ec-uiSelBg:#39414a;--ec-uiSelFg:#e1e4e8;--ec-focusBrd:#005cc5;--ec-sbThumbCol:#6a737d33;--ec-sbThumbHoverCol:#6a737dd1;--ec-tm-lineMarkerAccentMarg:0rem;--ec-tm-lineMarkerAccentWd:0.15rem;--ec-tm-lineMarkerLabelPadInl:0.2rem;--ec-tm-lineMarkerLabelCol:white;--ec-tm-lineDiffIndMargLeft:0.3rem;--ec-tm-inlMarkerBrdWd:1.5px;--ec-tm-inlMarkerBrdRad:0.2rem;--ec-tm-inlMarkerPad:0.15rem;--ec-tm-insDiffIndContent:'+';--ec-tm-delDiffIndContent:'-';--ec-tm-markBg:#264a8980;--ec-tm-markBrdCol:#5570b3d0;--ec-tm-insBg:#26561c80;--ec-tm-insBrdCol:#4e7e41d0;--ec-tm-insDiffIndCol:#7eb070d0;--ec-tm-delBg:#81322b80;--ec-tm-delBrdCol:#ae594fd0;--ec-tm-delDiffIndCol:#e68a7ed0;--ec-frm-shdCol:#0000005b;--ec-frm-frameBoxShdCssVal:0.1rem 0.1rem 0.2rem #0000005b;--ec-frm-edActTabBg:#24292e;--ec-frm-edActTabFg:#e1e4e8;--ec-frm-edActTabBrdCol:transparent;--ec-frm-edActTabIndHt:1.5px;--ec-frm-edActTabIndTopCol:#f9826c;--ec-frm-edActTabIndBtmCol:#24292e;--ec-frm-edTabsMargInlStart:0;--ec-frm-edTabsMargBlkStart:0;--ec-frm-edTabBrdRad:0.3rem;--ec-frm-edTabBarBg:#1f2428;--ec-frm-edTabBarBrdCol:#1b1f23;--ec-frm-edTabBarBrdBtmCol:#1b1f23;--ec-frm-edBg:#24292e;--ec-frm-trmTtbFg:#e1e4e8;--ec-frm-trmTtbDotsFg:#e1e4e8;--ec-frm-trmTtbDotsOpa:0.15;--ec-frm-trmTtbBg:#24292e;--ec-frm-trmTtbBrdBtmCol:#1b1f23;--ec-frm-trmBg:#1f2428;--ec-frm-inlBtnFg:#e1e4e8;--ec-frm-inlBtnBg:#e1e4e8;--ec-frm-inlBtnBgIdleOpa:0;--ec-frm-inlBtnBgHoverOrFocusOpa:0.2;--ec-frm-inlBtnBgActOpa:0.3;--ec-frm-inlBtnBrd:#e1e4e8;--ec-frm-inlBtnBrdOpa:0.4;--ec-frm-tooltipSuccessBg:#228739;--ec-frm-tooltipSuccessFg:white;--ec-frm-copyIcon:url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2024%2024'%20fill%3D'none'%20stroke%3D'black'%20stroke-width%3D'1.75'%3E%3Cpath%20d%3D'M3%2019a2%202%200%200%201-1-2V2a2%202%200%200%201%201-1h13a2%202%200%200%201%202%201'%2F%3E%3Crect%20x%3D'6'%20y%3D'5'%20width%3D'16'%20height%3D'18'%20rx%3D'1.5'%20ry%3D'1.5'%2F%3E%3C%2Fsvg%3E");--ec-frm-trmIcon:url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2060%2016'%20preserveAspectRatio%3D'xMidYMid%20meet'%3E%3Ccircle%20cx%3D'8'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'30'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'52'%20cy%3D'8'%20r%3D'8'%2F%3E%3C%2Fsvg%3E")}.expressive-code .ec-line :where(span[style^='--']:not([class])),:root:not([data-theme='github-dark']) .expressive-code[data-theme='github-dark'] .ec-line :where(span[style^='--']:not([class])){color:var(--0, inherit);background-color:var(--0bg, transparent);font-style:var(--0fs, inherit);font-weight:var(--0fw, inherit);text-decoration:var(--0td, inherit)}@media (prefers-color-scheme: light){:root:not([data-theme='github-dark']){--ec-brdCol:#e1e4e8;--ec-codeBg:#fff;--ec-codeFg:#24292e;--ec-codeSelBg:#0366d625;--ec-gtrFg:#1b1f2381;--ec-gtrBrdCol:#1b1f2333;--ec-gtrHlFg:#24292eab;--ec-uiSelBg:#e2e5e9;--ec-uiSelFg:#2f363d;--ec-focusBrd:#2188ff;--ec-sbThumbCol:#959da533;--ec-sbThumbHoverCol:#959da5eb;--ec-tm-markBg:#9fb6ff80;--ec-tm-insBg:#94c68480;--ec-tm-insDiffIndCol:#3a692fd0;--ec-tm-delBg:#fea09280;--ec-tm-delDiffIndCol:#97453dd0;--ec-frm-shdCol:#00000028;--ec-frm-frameBoxShdCssVal:0.1rem 0.1rem 0.2rem #00000028;--ec-frm-edActTabBg:#fff;--ec-frm-edActTabFg:#2f363d;--ec-frm-edActTabIndBtmCol:#fff;--ec-frm-edTabBarBg:#f6f8fa;--ec-frm-edTabBarBrdCol:#e1e4e8;--ec-frm-edTabBarBrdBtmCol:#e1e4e8;--ec-frm-edBg:#fff;--ec-frm-trmTtbFg:#2f363d;--ec-frm-trmTtbDotsFg:#2f363d;--ec-frm-trmTtbBg:#fff;--ec-frm-trmTtbBrdBtmCol:#e1e4e8;--ec-frm-trmBg:#f6f8fa;--ec-frm-inlBtnFg:#24292e;--ec-frm-inlBtnBg:#24292e;--ec-frm-inlBtnBrd:#24292e;--ec-frm-tooltipSuccessBg:#208638}:root:not([data-theme='github-dark']) .expressive-code .ec-line :where(span[style^='--']:not([class])){color:var(--1, inherit);background-color:var(--1bg, transparent);font-style:var(--1fs, inherit);font-weight:var(--1fw, inherit);text-decoration:var(--1td, inherit)}}:root[data-theme='github-light'] .expressive-code:not([data-theme='github-dark']),.expressive-code[data-theme='github-light']{--ec-brdCol:#e1e4e8;--ec-codeBg:#fff;--ec-codeFg:#24292e;--ec-codeSelBg:#0366d625;--ec-gtrFg:#1b1f2381;--ec-gtrBrdCol:#1b1f2333;--ec-gtrHlFg:#24292eab;--ec-uiSelBg:#e2e5e9;--ec-uiSelFg:#2f363d;--ec-focusBrd:#2188ff;--ec-sbThumbCol:#959da533;--ec-sbThumbHoverCol:#959da5eb;--ec-tm-markBg:#9fb6ff80;--ec-tm-insBg:#94c68480;--ec-tm-insDiffIndCol:#3a692fd0;--ec-tm-delBg:#fea09280;--ec-tm-delDiffIndCol:#97453dd0;--ec-frm-shdCol:#00000028;--ec-frm-frameBoxShdCssVal:0.1rem 0.1rem 0.2rem #00000028;--ec-frm-edActTabBg:#fff;--ec-frm-edActTabFg:#2f363d;--ec-frm-edActTabIndBtmCol:#fff;--ec-frm-edTabBarBg:#f6f8fa;--ec-frm-edTabBarBrdCol:#e1e4e8;--ec-frm-edTabBarBrdBtmCol:#e1e4e8;--ec-frm-edBg:#fff;--ec-frm-trmTtbFg:#2f363d;--ec-frm-trmTtbDotsFg:#2f363d;--ec-frm-trmTtbBg:#fff;--ec-frm-trmTtbBrdBtmCol:#e1e4e8;--ec-frm-trmBg:#f6f8fa;--ec-frm-inlBtnFg:#24292e;--ec-frm-inlBtnBg:#24292e;--ec-frm-inlBtnBrd:#24292e;--ec-frm-tooltipSuccessBg:#208638}:root[data-theme='github-light'] .expressive-code:not([data-theme='github-dark']) .ec-line :where(span[style^='--']:not([class])),.expressive-code[data-theme='github-light'] .ec-line :where(span[style^='--']:not([class])){color:var(--1, inherit);background-color:var(--1bg, transparent);font-style:var(--1fs, inherit);font-weight:var(--1fw, inherit);text-decoration:var(--1td, inherit)}</style><script type="module">try{(()=>{var e=window.requestIdleCallback||(e=>setTimeout(e,1)),t=window.cancelIdleCallback||clearTimeout;function r(e,t){e.querySelectorAll?.(".expressive-code pre > code").forEach(e=>{let r=e.parentElement;r&&t.observe(r)})}var o=function(r){let o,n,a=new Set;return new ResizeObserver(i=>{i.forEach(e=>a.add(e.target)),o&&clearTimeout(o),n&&t(n),o=setTimeout(()=>{n&&t(n),n=e(()=>{a.forEach(e=>r(e)),a.clear()})},250)})}(function(e){if(!e)return;let t=null!==e.getAttribute("tabindex"),r=e.scrollWidth>e.clientWidth;r&&!t?(e.setAttribute("tabindex","0"),e.setAttribute("role","region")):!r&&t&&(e.removeAttribute("tabindex"),e.removeAttribute("role"))});r(document,o),new MutationObserver(e=>e.forEach(e=>e.addedNodes.forEach(e=>{r(e,o)}))).observe(document.body,{childList:!0,subtree:!0}),document.addEventListener("astro:page-load",()=>{r(document,o)})})()}catch(e){console.error("[EC] tabindex-js-module failed:",e)}</script><script type="module">try{(()=>{async function e(e){let t=e.currentTarget,o=t.dataset,n=!1,a=o.code.replace(/\u007f/g,"\n");try{await navigator.clipboard.writeText(a),n=!0}catch{n=function(e){let t=document.createElement("pre");Object.assign(t.style,{opacity:"0",pointerEvents:"none",position:"absolute",overflow:"hidden",left:"0",top:"0",width:"20px",height:"20px",webkitUserSelect:"auto",userSelect:"all"}),t.ariaHidden="true",t.textContent=e,document.body.appendChild(t);let o=document.createRange();o.selectNode(t);let n=getSelection();if(!n)return!1;n.removeAllRanges(),n.addRange(o);let a=!1;try{a=document.execCommand("copy")}finally{n.removeAllRanges(),document.body.removeChild(t)}return a}(a)}if(!n||t.parentNode?.querySelector(".feedback"))return;let d=t.parentNode?.querySelector("[aria-live]"),r=document.createElement("div");r.classList.add("feedback"),r.append(o.copied),d.append(r),r.offsetWidth,requestAnimationFrame(()=>r?.classList.add("show"));let c=()=>!r||r.classList.remove("show"),i=()=>{!r||parseFloat(getComputedStyle(r).opacity)>0||(r.remove(),r=void 0)};setTimeout(c,1500),setTimeout(i,2500),t.addEventListener("blur",c),r.addEventListener("transitioncancel",i),r.addEventListener("transitionend",i)}function t(t){t.querySelectorAll?.(".expressive-code .copy button").forEach(t=>t.addEventListener("click",e))}t(document),new MutationObserver(e=>e.forEach(e=>e.addedNodes.forEach(e=>{t(e)}))).observe(document.body,{childList:!0,subtree:!0}),document.addEventListener("astro:page-load",()=>{t(document)})})()}catch(e){console.error("[EC] copy-js-module failed:",e)}</script><figure class="frame"><figcaption class="header"></figcaption><pre tabindex="0" class="codeBlockStandalone_MEMb thin-scrollbar codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><code class="codeBlockLines_e6Vv"><div class="ec-line"><div class="code"><span style="--0:#99A0A6;--1:#616972">// From `ArraysSupport`</span></div></div><div class="ec-line"><div class="code"><span style="--0:#99A0A6;--1:#616972">/**</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">* A soft maximum array length imposed by array growth computations.</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">* Some JVMs (such as HotSpot) have an implementation limit that will cause</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">*</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">*     OutOfMemoryError("Requested array size exceeds VM limit")</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">*</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">* to be thrown if a request is made to allocate an array of some length near</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">* Integer.MAX_VALUE, even if there is sufficient heap available. The actual</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">* limit might depend on some JVM implementation-specific characteristics such</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">* as the object header size. The soft maximum value is chosen conservatively so</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">* as to be smaller than any implementation limit that is likely to be encountered.</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#99A0A6;--1:#616972"> </span></span><span style="--0:#99A0A6;--1:#616972">*/</span></div></div><div class="ec-line"><div class="code"><span style="--0:#F97583;--1:#BF3441">public</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">static</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">final</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">int</span><span style="--0:#E1E4E8;--1:#24292E"> SOFT_MAX_ARRAY_LENGTH </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> Integer.MAX_VALUE </span><span style="--0:#F97583;--1:#BF3441">-</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#79B8FF;--1:#005CC5">8</span><span style="--0:#E1E4E8;--1:#24292E">;</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="// From `ArraysSupport`/** * A soft maximum array length imposed by array growth computations. * Some JVMs (such as HotSpot) have an implementation limit that will cause * *     OutOfMemoryError(&quot;Requested array size exceeds VM limit&quot;) * * to be thrown if a request is made to allocate an array of some length near * Integer.MAX_VALUE, even if there is sufficient heap available. The actual * limit might depend on some JVM implementation-specific characteristics such * as the object header size. The soft maximum value is chosen conservatively so * as to be smaller than any implementation limit that is likely to be encountered. */public static final int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;"><div></div></button></div></figure></div>
<p>To which I thought... really? So I gave it a quick try with Microsoft's OpenJDK using <code>new Object[Integer.MAX_VALUE]</code>, and lo and behold:</p>
<div class="expressive-code"><figure class="frame"><figcaption class="header"></figcaption><pre tabindex="0" class="codeBlockStandalone_MEMb thin-scrollbar codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><code class="codeBlockLines_e6Vv"><div class="ec-line"><div class="code"><span style="--0:#e1e4e8;--1:#24292e">Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="Exception in thread &quot;main&quot; java.lang.OutOfMemoryError: Requested array size exceeds VM limit"><div></div></button></div></figure></div>
<p>It did throw the error. And trying with <code>new Object[Integer.MAX_VALUE - 8]</code> created the array successfully, at the cost of ~8GiBs of heap usage.</p>
<p>I could've left it there with a 'neat' and moved on, but the 'some JVMs' part kept rattling around in my head. Since it's 'some', wouldn't that mean there exists a JVM that allows <code>new Object[Integer.MAX_VALUE]</code>? Actually, what <em>is</em> the maximum number of elements an array can hold?</p>
<p>So, I decided to test it.</p>
<p>Using <a href="https://sdkman.io/" target="_blank" rel="noopener noreferrer" class="">SDKMAN!</a>, I downloaded the latest release of every JVM, including the <a href="https://github.com/JetBrains/JetBrainsRuntime" target="_blank" rel="noopener noreferrer" class="">JetBrains Runtime (JBR)</a> separately, into a Debian 13 container and ran a quick little allocation test using:</p>
<div class="expressive-code"><figure class="frame"><figcaption class="header"></figcaption><pre tabindex="0" class="codeBlockStandalone_MEMb thin-scrollbar codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><code class="codeBlockLines_e6Vv"><div class="ec-line"><div class="code"><span style="--0:#F97583;--1:#BF3441">public</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">class</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">AllocationTest</span><span style="--0:#E1E4E8;--1:#24292E"> {</span></div></div><div class="ec-line"><div class="code">
</div></div><div class="ec-line"><div class="code"><span class="indent">    </span><span style="--0:#F97583;--1:#BF3441">public</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">static</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">void</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#B392F0;--1:#6F42C1">main</span><span style="--0:#E1E4E8;--1:#24292E">(</span><span style="--0:#F97583;--1:#BF3441">String</span><span style="--0:#E1E4E8;--1:#24292E">[] </span><span style="--0:#FFAB70;--1:#AE4B07">args</span><span style="--0:#E1E4E8;--1:#24292E">) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#99A0A6;--1:#616972">// Start with max size</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#F97583;--1:#BF3441">int</span><span style="--0:#E1E4E8;--1:#24292E"> size </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> Integer.MAX_VALUE;</span></div></div><div class="ec-line"><div class="code"><span class="indent">        </span><span style="--0:#F97583;--1:#BF3441">while</span><span style="--0:#E1E4E8;--1:#24292E"> (</span><span style="--0:#79B8FF;--1:#005CC5">true</span><span style="--0:#E1E4E8;--1:#24292E">) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">            </span><span style="--0:#F97583;--1:#BF3441">try</span><span style="--0:#E1E4E8;--1:#24292E"> {</span></div></div><div class="ec-line"><div class="code"><span class="indent">                </span><span style="--0:#F97583;--1:#BF3441">Object</span><span style="--0:#E1E4E8;--1:#24292E">[] maxCapacity </span><span style="--0:#F97583;--1:#BF3441">=</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">new</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">Object</span><span style="--0:#E1E4E8;--1:#24292E">[size];</span></div></div><div class="ec-line"><div class="code"><span class="indent">                </span><span style="--0:#99A0A6;--1:#616972">// Break after successful allocation</span></div></div><div class="ec-line"><div class="code"><span class="indent">                </span><span style="--0:#F97583;--1:#BF3441">break</span><span style="--0:#E1E4E8;--1:#24292E">;</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">            </span></span><span style="--0:#E1E4E8;--1:#24292E">} </span><span style="--0:#F97583;--1:#BF3441">catch</span><span style="--0:#E1E4E8;--1:#24292E"> (OutOfMemoryError </span><span style="--0:#FFAB70;--1:#AE4B07">error</span><span style="--0:#E1E4E8;--1:#24292E">) {</span></div></div><div class="ec-line"><div class="code"><span class="indent">                </span><span style="--0:#99A0A6;--1:#616972">// Too large, reduce size</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">                </span></span><span style="--0:#E1E4E8;--1:#24292E">size</span><span style="--0:#F97583;--1:#BF3441">--</span><span style="--0:#E1E4E8;--1:#24292E">;</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">            </span></span><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">        </span></span><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">        </span></span><span style="--0:#E1E4E8;--1:#24292E">System.out.</span><span style="--0:#B392F0;--1:#6F42C1">println</span><span style="--0:#E1E4E8;--1:#24292E">(</span><span style="--0:#9ECBFF;--1:#032F62">"Max Size: "</span><span style="--0:#E1E4E8;--1:#24292E"> </span><span style="--0:#F97583;--1:#BF3441">+</span><span style="--0:#E1E4E8;--1:#24292E"> size);</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#E1E4E8;--1:#24292E">    </span></span><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div><div class="ec-line"><div class="code"><span style="--0:#E1E4E8;--1:#24292E">}</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="public class AllocationTest {    public static void main(String[] args) {        // Start with max size        int size = Integer.MAX_VALUE;        while (true) {            try {                Object[] maxCapacity = new Object[size];                // Break after successful allocation                break;            } catch (OutOfMemoryError error) {                // Too large, reduce size                size--;            }        }        System.out.println(&quot;Max Size: &quot; + size);    }}"><div></div></button></div></figure></div>
<p>Nothing to complex, it attempts to construct an array with the given size, and if an OOM is thrown, it repeats the process with one number smaller until does. With 18GiBs to play around with, I got the following results:</p>
<table><thead><tr><th style="text-align:center">Implementation</th><th style="text-align:center">Latest Version</th><th style="text-align:left">Max Allocation Size</th></tr></thead><tbody><tr><td style="text-align:center">BiSheng (Huawei)</td><td style="text-align:center">21</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Corretto (Amazon)</td><td style="text-align:center">26</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Dragonwell (Alibaba)</td><td style="text-align:center">21</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">GraalVM (GraalVM Community)</td><td style="text-align:center">25</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">GraalVM (Oracle)</td><td style="text-align:center">25</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Java SE Development Kit (Oracle)</td><td style="text-align:center">26</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Kona (Tencent)</td><td style="text-align:center">21</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Liberica (Bellsoft)</td><td style="text-align:center">26</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Liberica NIK (Bellsoft)</td><td style="text-align:center">25</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Mandrel (Red Hat)</td><td style="text-align:center">25</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">OpenJDK (Microsoft)</td><td style="text-align:center">25</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">OpenJDK (jdk.java.net)</td><td style="text-align:center">26</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">SapMachine (SAP)</td><td style="text-align:center">26</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Semeru (IBM)</td><td style="text-align:center">26</td><td style="text-align:left">2,147,483,647</td></tr><tr><td style="text-align:center">Temurin (Eclipse)</td><td style="text-align:center">26</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Trava (Trava)</td><td style="text-align:center">11</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">Zulu (Azul Systems)</td><td style="text-align:center">26</td><td style="text-align:left">2,147,483,645</td></tr><tr><td style="text-align:center">JetBrains Runtime</td><td style="text-align:center">25</td><td style="text-align:left">2,147,483,645</td></tr></tbody></table>
<p>Strangely, only IBM's Semeru JVM allowed the array to allocate an <code>Integer.MAX_VALUE</code> of elements. Even stranger, the other JVMs allocated <code>Integer.MAX_VALUE - 2</code>, which is six greater than the <code>ArraysSupport.SOFT_MAX_ARRAY_LENGTH</code>.</p>
<p>So, for the first part, that's because of the underlying base making up the JVMs. Every single one except for IBM's Semeru is based off of HotSpot, where that comment comes from. Meanwhile, Semeru is based on OpenJ9, which provides a different implementation of the JVM spec. We can see that even more clearly when trying to go outside the maximum bounds of an <code>ArrayList</code> via <code>add</code>.</p>
<p>For HotSpot JVMs:</p>
<div class="expressive-code"><figure class="frame"><figcaption class="header"></figcaption><pre tabindex="0" class="codeBlockStandalone_MEMb thin-scrollbar codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><code class="codeBlockLines_e6Vv"><div class="ec-line"><div class="code"><span style="--0:#e1e4e8;--1:#24292e">Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.Arrays.copyOf(Arrays.java:3509)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.Arrays.copyOf(Arrays.java:3478)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.ArrayList.grow(ArrayList.java:238)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.ArrayList.grow(ArrayList.java:245)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.ArrayList.add(ArrayList.java:484)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.ArrayList.add(ArrayList.java:497)</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="Exception in thread &quot;main&quot; java.lang.OutOfMemoryError: Requested array size exceeds VM limit        at java.base/java.util.Arrays.copyOf(Arrays.java:3509)        at java.base/java.util.Arrays.copyOf(Arrays.java:3478)        at java.base/java.util.ArrayList.grow(ArrayList.java:238)        at java.base/java.util.ArrayList.grow(ArrayList.java:245)        at java.base/java.util.ArrayList.add(ArrayList.java:484)        at java.base/java.util.ArrayList.add(ArrayList.java:497)"><div></div></button></div></figure></div>
<p>And for Semeru's OpenJ9 JVM:</p>
<div class="expressive-code"><figure class="frame"><figcaption class="header"></figcaption><pre tabindex="0" class="codeBlockStandalone_MEMb thin-scrollbar codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><code class="codeBlockLines_e6Vv"><div class="ec-line"><div class="code"><span style="--0:#e1e4e8;--1:#24292e">Exception in thread "main" java.lang.OutOfMemoryError: Required array length 2147483647 + 1 is too large</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/jdk.internal.util.ArraysSupport.hugeLength(ArraysSupport.java:914)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/jdk.internal.util.ArraysSupport.newLength(ArraysSupport.java:907)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.ArrayList.grow(ArrayList.java:235)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.ArrayList.grow(ArrayList.java:245)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.ArrayList.add(ArrayList.java:484)</span></div></div><div class="ec-line"><div class="code"><span class="indent"><span style="--0:#e1e4e8;--1:#24292e">        </span></span><span style="--0:#e1e4e8;--1:#24292e">at java.base/java.util.ArrayList.add(ArrayList.java:497)</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="Exception in thread &quot;main&quot; java.lang.OutOfMemoryError: Required array length 2147483647 + 1 is too large        at java.base/jdk.internal.util.ArraysSupport.hugeLength(ArraysSupport.java:914)        at java.base/jdk.internal.util.ArraysSupport.newLength(ArraysSupport.java:907)        at java.base/java.util.ArrayList.grow(ArrayList.java:235)        at java.base/java.util.ArrayList.grow(ArrayList.java:245)        at java.base/java.util.ArrayList.add(ArrayList.java:484)        at java.base/java.util.ArrayList.add(ArrayList.java:497)"><div></div></button></div></figure></div>
<p>Same OOM, but different reasoning. Though, the OpenJ9 error doesn't make much sense since it implies it would let you create a larger array if it wasn't limited to a signed integer.</p>
<p>As for why they allow allocation up to those values, I have no idea. After asking around, someone mentioned that the Java Virtual Machine Specification (JVMS) defines that the first two entries could be taken up by the array's length followed by its data type, but I was unable to find such a explanation within the doc. Most likely, it's just up to the JVM to choose how arrays are implemented. After all, "the soft maximum value is chosen conservatively so as to be smaller than any implementation limit that is likely to be encountered." (From <code>ArraysSupport.SOFT_MAX_ARRAY_LENGTH</code>)</p>
<p>Now, of course there are other JVMs other than the two big ones everyone forks, so what about those? Well, the problem is that most of those JVMs are implemented for pre-8 versions, which fails spectacularly in modern containers with modern libraries. To actually get it working in a container, I'd have to build an old linux distro from scratch, install the dependencies from some archival site, and then just hope there isn't any weird implementations preventing me from building it from source. So I thought about it...</p>
<p>...and moved on.</p>
<p>What? That's way too much effort for "how big can I make my array" when the likelihood of me actually ever reaching that limit is slim to none. I'd much rather go down some different rabbit holes.</p>
<p>So all in all, the main difference between the array implementations is that I can store two more elements in Semeru than the others.</p>
<p>...yeah, definitely an interesting use of my time.</p>]]></content>
        <author>
            <name>ChampionAsh5357</name>
            <uri>https://github.com/ChampionAsh5357</uri>
        </author>
    </entry>
</feed>