[{"data":1,"prerenderedAt":41},["ShallowReactive",2],{"$fmNiSGbkpRvOUKFKkJA2KeBYju1MwbSVUVJgeSMyHAX0":3},{"slug":4,"title":5,"description":6,"date":7,"tags":8,"tools":13,"draft":15,"html":16,"toc":17,"minutes":40},"final-grade-formula","What Do I Need on My Final? Deriving the Formula Step by Step","The one-line equation behind every final grade calculator, solved for the final score, with what a result above 100% or below 0% really means.","2026-09-25",[9,10,11,12],"math","calculators","students","typescript",[14],"final-grade-calculator",false,"\u003Cp>It’s the week before finals. Your gradebook says 84%, the syllabus says the final counts for 30%, and you want an 85 in the course. You need a number to aim for, not a vague “do well”. I built the \u003Ca href=\"\u002Ffinal-grade-calculator\">final grade calculator\u003C\u002Fa> to give that number, and the math behind it fits on one line. The interesting parts are the answers that look wrong: a required score of 170%, or −80%.\u003C\u002Fp>\n\u003Ch2 id=\"the-model-a-weighted-average-of-two-parts\">The model: a weighted average of two parts\u003C\u002Fh2>\n\u003Cp>Most syllabuses describe the final as a fixed share of the course grade: “Final exam: 30%”. Everything else (homework, quizzes, the midterm, projects) makes up the other 70%, and your current grade is the average of that part so far.\u003C\u002Fp>\n\u003Cp>So the course grade is a weighted average of two numbers: \u003Cstrong>course = current × (1 − w) + final × w\u003C\u002Fstrong>.\u003C\u002Fp>\n\u003Cp>Here \u003Ccode>w\u003C\u002Fcode> is the final’s weight as a fraction (30% is 0.3), and every grade is a percentage from 0 to 100. With a current grade of 84 and a final worth 30%, an 80 on the final gives 84 × 0.7 + 80 × 0.3 = 58.8 + 24 = 82.8.\u003C\u002Fp>\n\u003Cp>That’s the whole model. It assumes your current grade won’t change before the final, which is why the page’s tips tell you to use the gradebook after all other work is marked.\u003C\u002Fp>\n\u003Ch2 id=\"solving-for-the-final\">Solving for the final\u003C\u002Fh2>\n\u003Cp>The question students ask runs the other way. You know the course grade you want (call it the target) and you need the final score. Start from the same equation, with the target on the left:\u003C\u002Fp>\n\u003Col>\n\u003Cli>target = current × (1 − w) + final × w\u003C\u002Fli>\n\u003Cli>target − current × (1 − w) = final × w\u003C\u002Fli>\n\u003Cli>final = (target − current × (1 − w)) ÷ w\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Step 2 moves the part you’ve already earned to the left. Step 3 divides by the weight. In the code it’s exactly that:\u003C\u002Fp>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#57606a;--shiki-dark:#8b949e\">\u002F\u002F Course grade = current × (1 − w) + final × w, so final = (target − current × (1 − w)) ÷ w\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">export\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> function\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> requiredFinal\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#b35309;--shiki-dark:#FFAB70\">current\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> number\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#b35309;--shiki-dark:#FFAB70\">weight\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> number\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#b35309;--shiki-dark:#FFAB70\">target\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> number\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> GradeResult\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> error\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> check\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(current, weight)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (error) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { ok: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">false\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, error }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> w\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> weight \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 100\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { ok: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">true\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, value: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">clean\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">((target \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> current \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">1\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> -\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> w)) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> w) }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>For the example: (85 − 84 × 0.7) ÷ 0.3 = (85 − 58.8) ÷ 0.3 = 26.2 ÷ 0.3 = 87.33%. The raw division gives 87.33333…; \u003Ccode>clean\u003C\u002Fcode> rounds it to 12 significant digits to drop floating-point noise, and the page shows two decimals.\u003C\u002Fp>\n\u003Cp>The division by \u003Ccode>w\u003C\u002Fcode> is also why the weight can’t be 0. A final worth nothing can’t move your grade, and the formula would divide by zero. \u003Ccode>check\u003C\u002Fcode> refuses a weight of 0 or less, a weight above 100%, and a negative current grade, each with its own message.\u003C\u002Fp>\n\u003Cp>A test makes sure the two directions agree: for a current grade of 76.5 and a final worth 35%, it takes the required score for an 82 and feeds it back into the course grade formula. It must come out at exactly 82.\u003C\u002Fp>\n\u003Ch2 id=\"when-the-answer-is-above-100-or-below-0\">When the answer is above 100% or below 0%\u003C\u002Fh2>\n\u003Cp>The formula doesn’t know that exam scores stop at 0 and 100. It just solves the equation. So it can return numbers no one can score, and those numbers are the most useful part of the result.\u003C\u002Fp>\n\u003Cp>Take a current grade of 70, a final worth 20%, and a goal of 90:\u003C\u002Fp>\n\u003Cp>(90 − 70 × 0.8) ÷ 0.2 = (90 − 56) ÷ 0.2 = 170%\u003C\u002Fp>\n\u003Cp>No final can give you 170%. The goal is out of reach. Now take a current grade of 95, a final worth 20%, and a goal of 60:\u003C\u002Fp>\n\u003Cp>(60 − 95 × 0.8) ÷ 0.2 = (60 − 76) ÷ 0.2 = −80%\u003C\u002Fp>\n\u003Cp>You already have 76 points of the course grade from the other 80%, more than the 60 you need. Even a 0 on the final keeps you above the goal.\u003C\u002Fp>\n\u003Cp>The code turns the number into one of three states:\u003C\u002Fp>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">export\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> function\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> verdict\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#b35309;--shiki-dark:#FFAB70\">required\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> number\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#b35309;--shiki-dark:#FFAB70\">maxScore\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 100\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> Verdict\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (required \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">&#x3C;=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 0\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'secured'\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> required \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">&#x3C;=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> maxScore \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">?\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'reachable'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> :\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'out-of-reach'\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"table-wrap\">\u003Ctable>\u003Cthead>\n\u003Ctr>\n\u003Cth>Required score\u003C\u002Fth>\n\u003Cth>State\u003C\u002Fth>\n\u003Cth>What the page says\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>0% or less\u003C\u002Ftd>\n\u003Ctd>secured\u003C\u002Ftd>\n\u003Ctd>“You’ve already secured 60%: even a 0 on the final keeps you there.” The answer shows 0%, never a negative number.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>above 0% up to 100%\u003C\u002Ftd>\n\u003Ctd>reachable\u003C\u002Ftd>\n\u003Ctd>“Score at least 87.33% on the final to finish with 85%.”\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>above 100%\u003C\u002Ftd>\n\u003Ctd>out of reach\u003C\u002Ftd>\n\u003Ctd>“Out of reach without extra credit. With 100% on the final, your course grade would be 76%.”\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\u003C\u002Fdiv>\u003Cp>For the 170% example, that best grade is 70 × 0.8 + 100 × 0.2 = 76%. Telling a student “76 is the most you can get” is more useful than a bare “impossible”, because it gives them a new, real target.\u003C\u002Fp>\n\u003Cp>\u003Ccode>verdict\u003C\u002Fcode> takes a maximum score, 100 by default. The tests check that 104% becomes reachable when the maximum is 110, for an exam with bonus questions. The page itself always uses 100.\u003C\u002Fp>\n\u003Ch2 id=\"one-table-for-every-letter-grade\">One table for every letter grade\u003C\u002Fh2>\n\u003Cp>A single target isn’t always what you want. Often the real question is “can I still get an A, or should I settle for a B?” So the page runs the same formula once for each cut-off on the common US scale (A from 90, B from 80, C from 70, D from 60) and shows the score you need for each, marked “Already secured” or “out of reach” where that applies.\u003C\u002Fp>\n\u003Cp>For a current 84 with a final worth 30%:\u003C\u002Fp>\n\u003Cdiv class=\"table-wrap\">\u003Ctable>\u003Cthead>\n\u003Ctr>\n\u003Cth>Grade\u003C\u002Fth>\n\u003Cth>Course grade\u003C\u002Fth>\n\u003Cth>Needed on the final\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>A\u003C\u002Ftd>\n\u003Ctd>90% or more\u003C\u002Ftd>\n\u003Ctd>104%, out of reach\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>B\u003C\u002Ftd>\n\u003Ctd>80% or more\u003C\u002Ftd>\n\u003Ctd>70.67%\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>C\u003C\u002Ftd>\n\u003Ctd>70% or more\u003C\u002Ftd>\n\u003Ctd>37.33%\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>D\u003C\u002Ftd>\n\u003Ctd>60% or more\u003C\u002Ftd>\n\u003Ctd>4%\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\u003C\u002Fdiv>\u003Cp>Cut-offs differ between schools, which the page says under the table. If yours uses different ones, type your own cut-off as the grade you want.\u003C\u002Fp>\n\u003Ch2 id=\"the-reverse-if-i-score\">The reverse: “If I score…”\u003C\u002Fh2>\n\u003Cp>After the exam, the question changes. You have a rough idea of how it went and you want to know what it does to your course grade. The bottom of the page takes a final score and runs the original equation forward, with \u003Ccode>courseGrade\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cp>84 × 0.7 + 75 × 0.3 = 58.8 + 22.5 = 81.3%\u003C\u002Fp>\n\u003Cp>It’s the same equation as before, solved for the other unknown. Keeping both directions as two small functions on one model, instead of two separate formulas, is what lets the test check one against the other.\u003C\u002Fp>\n\u003Ch2 id=\"what-it-doesn-t-model\">What it doesn’t model\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Grades that aren’t a fixed share.\u003C\u002Fstrong> Some courses drop your lowest quiz, replace the midterm with the final if the final is higher, or require a minimum score on the final to pass at all. The formula can’t know these rules.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Points instead of percentages.\u003C\u002Fstrong> If your gradebook shows 425 of 500 points, turn that into 85% first. The \u003Ca href=\"\u002Fpercentage-calculator\">percentage calculator\u003C\u002Fa> does it.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Work that’s still due.\u003C\u002Fstrong> If homework or a project is still open, your current grade can move, and so does the score you need.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"try-it\">Try it\u003C\u002Fh2>\n\u003Cp>The \u003Ca href=\"\u002Ffinal-grade-calculator\">final grade calculator\u003C\u002Fa> shows the score you need for your goal, the table for each letter grade, and what any final score would do to your course grade. Other calculators for students are in \u003Ca href=\"\u002Fcalculators\">calculators\u003C\u002Fa>.\u003C\u002Fp>\n",[18,22,25,28,31,34,37],{"id":19,"text":20,"level":21},"the-model-a-weighted-average-of-two-parts","The model: a weighted average of two parts",2,{"id":23,"text":24,"level":21},"solving-for-the-final","Solving for the final",{"id":26,"text":27,"level":21},"when-the-answer-is-above-100-or-below-0","When the answer is above 100% or below 0%",{"id":29,"text":30,"level":21},"one-table-for-every-letter-grade","One table for every letter grade",{"id":32,"text":33,"level":21},"the-reverse-if-i-score","The reverse: “If I score…”",{"id":35,"text":36,"level":21},"what-it-doesn-t-model","What it doesn’t model",{"id":38,"text":39,"level":21},"try-it","Try it",5,1792325805343]