Noch nicht auf Deutsch – hier die englische Seite.

How to check that an AI-made calculator matches your Excel sheet

Quick answer

Run the same 10 to 20 input sets through the sheet and the AI's page, and compare every output to a tolerance you set first. Include zeros, blanks, the limits, and each IF branch. Most mismatches come from Excel's own rules: ROUND's halves, 15-digit display, blank cells, Goal Seek's stopping point, and dates.

Get a link for my calculator

Free plan: no credit card, 1 published page. A private link or a password comes with Pro, $12 a month.

On this page

ChatGPT, Claude, or Gemini rewrote your workbook as an HTML calculator, and the first answer looks right. Before the crew relies on it, the page has to give the sheet's answer for every case they'll type, including the odd ones.

This guide is only about the numbers. For the links, buttons, and phone layout, use the general check for an AI-made page; to build the calculator in the first place, see turning an Excel calculator into a web app. Microsoft's Excel help quoted here was read on November 6, 2026. The JavaScript results are from our own script, run that day on Node.js 22 and in headless Chromium.

Run the same cases through both, to a stated tolerance

  1. Pick 10 to 20 input sets. Take 4 to 6 real jobs from the last month. Then add the edges: a zero, a blank box, the smallest and largest value the page allows, a value that lands exactly on a rounding step (a 5 in the last place you round to), and a negative number if one can happen.
  2. Cover every branch. One case for each side of every IF, with one right on the boundary (if the sheet says >=, test the boundary value itself). One case for each lookup table's first row, last row, and an input below the first key.
  3. Add a case that should fail. If the sheet gives #DIV/0! or #NUM!, the page should say so in words, not show Infinity, NaN, or a number.
  4. Write the expected values from Excel, with all the intermediate cells, not only the final answer. An intermediate value is where you'll find the cause when a case fails.
  5. Set the tolerance before you look. A result shown to 2 decimals must match exactly once both are rounded to 2 decimals. An unrounded value matches when it differs by less than 0.000000001 of its size, or by less than 0.000000001 when it's below 1, so an expected 0 can match. A solver's result matches within the tolerance you gave the solver.

In Excel, with the sheet's value in C2 and the page's in D2, these flag each row. For a result shown to 2 decimals:

=IF(ROUND(D2,2)=ROUND(C2,2),"PASS","FAIL")

For an unrounded value (MAX(1,…) makes the check absolute below 1):

=IF(ABS(D2-C2)<=1E-9*MAX(1,ABS(C2)),"PASS","FAIL")

Anything outside the tolerance is a different formula, a different rounding, or a different input. The rest of this guide is how to tell which.

A test table to copy

Keep it as a Tests sheet in the workbook. The calculator's own cells hold one case at a time, so each row needs its own copy of the formulas:

  • Formulas in every row. Copy the calculator's formulas into the row's expected columns, pointing at that row's inputs instead of the calculator's cells, and fill them down. The rows update when you change an input; when you change a formula in the calculator, copy it across again.
  • Or values, one case at a time. Type each case into the calculator, copy its results, and paste them into the row with Paste Values. After any change to the sheet, do it again for every row.

Put the inputs first, in the order the page asks for them, then the expected values, and the notes last, so the cells you copy for the page sit side by side:

Input 1 (unit)Input 2 (unit)Input 3 (unit)Expected 1Expected 2CaseWhy it's thereTolerancePageResult
1A real job2 decimals
2A real job2 decimals
03Zero2 decimals
(blank)4Blank box2 decimals
5Smallest allowed2 decimals
6Largest allowed2 decimals
7On a rounding half2 decimals
8IF boundary, exactly2 decimals
#N/A9Below the lookup tablean error message
#DIV/0!10Should failan error message

For the page, select the cells from the first input to the last expected value, not the Case, Why, Tolerance, Page, or Result columns. Copied cells can carry what a cell shows, such as a 7.5% shown as 8%. So first make every cell show all its decimals: keep a percent cell as a percentage and add decimal places until 7.5% shows as 7.5%, and set the other cells to General. The test mode below reads 7.5% as 7.5. Paste the rows with the tabs Excel puts between cells: an empty cell keeps its place only between tabs. Rows 9 and 10 aren't pasted: try them by hand and check the page's message.

Turning an Excel calculator into a web app has this table filled in for a concrete order sheet: 8 cases, 2 of which catch mistakes an AI version can make.

Where Excel and JavaScript disagree

Excel and JavaScript store numbers the same way. Microsoft says "Microsoft Excel was designed around the IEEE 754 specification", and MDN says a JavaScript number "is a double-precision 64-bit binary format IEEE 754 value". The differences are in the rules on top:

WhatExcelJavaScriptWhat to ask the AI for
Rounding a halfROUND goes away from zero: -1.475 to 2 places is -1.48Math.round goes toward +∞: -1.47The excelRound function below
Rounding in a macroVBA's Round "returns something commonly referred to as bankers rounding"No built-in banker's roundingBanker's rounding only where the macro used VBA's Round
Digits shown15 significant digitsUp to 17Compare with a tolerance; display with the sheet's decimals
A sum near zeroExcel 97 and later show 0 for =1.333+1.225-1.333-1.225-2.220446049250313e-16Round for display; never test === 0
A blank cell0 in =A1+B1; skipped by AVERAGE and IRRNumber("") is 0, parseFloat("") is NaNThe sheet's rule for each input, written down
A percent cellShows 5%, holds 0.05Whatever the box was toldOne rule, stated beside the box
Goal Seek, IRRStops at its own toleranceStops where the AI's loop saysA stated tolerance and an iteration cap
DatesSerial numbers from 1900, with a February 29, 1900Milliseconds from 1970, in UTCThe conversion below, and dates as text

ROUND rounds halves away from zero

Microsoft's ROUND page gives 7 examples. We ran each through the 3 ways an AI usually rounds in JavaScript:

Excel formulaExcel's result (Microsoft)Math.round(x*10^d)/10^dx.toFixed(d)excelRound(x, d)
=ROUND(2.15, 1)2.22.2"2.1"2.2
=ROUND(2.149, 1)2.12.1"2.1"2.1
=ROUND(-1.475, 2)-1.48-1.47"-1.48"-1.48
=ROUND(21.5, -1)2020(no negative places)20
=ROUND(626.3,-3)10001000(no negative places)1000
=ROUND(1.98,-1)00(no negative places)0
=ROUND(-50.55,-2)-100-100(no negative places)-100
  • Math.round gets negative halves wrong. MDN: "If the fractional portion is exactly 0.5, the argument is rounded to the next integer in the direction of +∞." So -147.5 becomes -147, and -1.475 comes out as -1.47.
  • toFixed gets some positive halves wrong. 2.15 is stored as 2.1499999999999999112, so toFixed(1) gives "2.1". MDN's own example: "(2.55).toFixed(1); // '2.5'", because 2.55 "can't be represented exactly by a float".
  • VBA is different again. Microsoft's VBA page: Round(0.12345,4) gives 0.1234, and WorksheetFunction.Round(0.12345,4) gives 0.1235. If the workbook's macro rounded with VBA, that step needs banker's rounding; a cell formula never does.

This function reproduced all 7 of Microsoft's examples, and both of Microsoft's WorksheetFunction.Round results, in our test. It rounds the number as Excel holds it, to 15 significant digits, then rounds the half away from zero:

function excelRound(x, digits) {
  if (!Number.isFinite(x)) return NaN;
  const p = 10 ** Math.abs(digits);
  const scaled = digits >= 0 ? Math.abs(x) * p : Math.abs(x) / p;
  const r = Math.round(Number(scaled.toPrecision(15)));
  const back = digits >= 0 ? r / p : r * p;
  return x < 0 ? -back : back;
}

Halves Microsoft doesn't list belong in your test table. For example, excelRound(1.005, 2) gives 1.01, while Math.round gives 1 and toFixed(2) gives "1.00": check that row against your own Excel.

Excel shows 15 significant digits, JavaScript up to 17

Excel's specifications page puts its number precision at 15 digits. Microsoft's floating-point article gives examples, and here is what JavaScript prints for each:

Microsoft's exampleExcel showsJavaScript printsJavaScript, toPrecision(15)
=(43.1-43.2)+1, 15 decimals0.8999999999999990.89999999999999860.899999999999999
0.000123456789012345 + 11.000123456789011.00012345678901231.00012345678901
=1.333+1.225-1.333-1.2250 (Excel 97 and later)-2.220446049250313e-16-2.22044604925031e-16
1.2E+200 + 1E+1001.2E+2001.2e+2001.20000000000000e+200

The third row is the one that bites. Microsoft says that since Excel 97, "Should an addition or subtraction operation result in a value at or very close to zero", Excel compensates for the error. JavaScript doesn't, so a page shows -2.2e-16 where the sheet shows 0, and an IF(x=0, …) takes the other branch. Round for display, and compare with a tolerance, never ===.

Excel adds the stored values, not the ones it shows

Microsoft: "if two cells each contain the value 10.005 and the cells are formatted to display values in currency format, the value $10.01 is displayed in each cell. If you add the two cells together, the result is $20.01". An AI that rounds each line before it adds gives $20.02, because it rounds 10.005 to 10.01 twice. Ask it to round only where the sheet has a ROUND.

The exception is a workbook with Set precision as displayed turned on, under File > Options > Advanced. Microsoft says it "permanently changes stored values in cells from full precision (15 digits) to whatever format, including decimal places, is displayed". Check that box before you test, and tell the AI if it's on.

Blank cells, spaces, and percent cells

  • A blank cell is 0 in arithmetic. Microsoft's Goal Seek page: "Because there is no value in cell B3, Excel assumes a 0% interest rate and, using the values in the example, returns a payment of $555.56." ICAEW's Excel Community, on =A1 + B1 with B1 blank: "Excel treats the blank as 0."
  • But some functions skip blanks. For AVERAGE, Microsoft says empty cells "are ignored; however, cells with the value zero are included", and IRR ignores them too. In Microsoft's IRR example, leaving the second year's cash flow blank moves the later years one period earlier: our IRR gives 3.4977% with the blank skipped, as Excel does, and 2.6740% if the page reads the blank as 0.
  • JavaScript has both behaviours. MDN: in Number(), "Empty or whitespace-only strings are converted to 0", while parseFloat("") is NaN. Ask for Number() where the sheet treats a blank as 0, and an error message where the sheet would break.
  • A space is not a blank in Excel. Microsoft: "Often #VALUE! occurs because your formula refers to other cells that contain spaces", which "can make a cell look blank, when in fact they are not blank". Number(" ") is 0 in JavaScript, so the page answers where the sheet gave an error.
  • Rate 0 is a branch. The textbook payment formula divides 0 by 0 at a 0% rate: our naive version returned NaN for Microsoft's blank-rate example, and a version with a rate-0 branch returned -555.56. It also matched Microsoft's 3 PMT examples: ($1,037.03), ($1,030.16), and ($129.08).
  • A percent cell holds a fraction. Microsoft: "if a cell contains the formula =10/100, the result of that calculation is 0.1. If you then format 0.1 as a percentage, the number will be correctly displayed as 10%". On the page, decide whether people type 10 or 0.1, write it beside the box, and divide by 100 once. A page that forgets turns 8.9% tax on 800 into 7,120 instead of 71.2, which the first test row catches.

Goal Seek, iteration, and IRR stop at a tolerance

Microsoft's Goal Seek example finds the interest rate that makes =PMT(B3/12,B2,B1) equal -900 for a loan of 100,000 over 180 months. "Goal Seek works only with one variable input value." A JavaScript version needs a search with a stopping rule, and the rule changes the answer:

Stop when the payment is withinRate foundHalvingsPayment at that rate
$0.507.019043%13-899.893251
$0.0057.020950%18-899.999956
$0.0000000017.020951%41-900.000000

Microsoft's Goal Seek page doesn't state Excel's stopping rule. For iterative calculation, Microsoft says "By default, Excel stops after 100 iterations, or when values change by less than 0.001." Give the AI the tolerance and the cap, have the page show what it reached ("rate 7.0210%, payment within $0.005, 18 steps"), and compare the sheet's result to that tolerance, not to every digit.

IRR is the same. Microsoft: "Starting with guess, IRR cycles through the calculation until the result is accurate within 0.00001 percent. If IRR can't find a result that works after 20 tries, the #NUM! error value is returned." Our Newton's method, with those rules, on Microsoft's example cash flows:

Microsoft's formulaExcel's result (Microsoft)Our resultTries
=IRR(A2:A7), 5 years8.7%8.6631%4
=IRR(A2:A6), 4 years-2.1%-2.1245%5
=IRR(A2:A4,-10%), 2 years-44.4%-44.3507%8

Microsoft says the 2-year case needs the -10% guess. From the default 10%, our loop settled on -138.5064%, a rate below -100% that means nothing. The page has to reject a result like that and show "no answer, try a different guess", as Excel shows #NUM!.

Dates are serial numbers, and Excel has a February 29, 1900

Microsoft: "In the 1900 date system, dates are calculated by using January 1, 1900, as a starting point," so "if you enter July 5, 2011, Excel converts the date to the serial number 40729". It also says "Microsoft Excel incorrectly assumes that the year 1900 is a leap year", and as a result "The WEEKDAY function returns incorrect values for dates before March 1, 1900."

Serial numberExcel's dateCounting days from December 30, 1899excelSerialToDate below
1January 1, 1900December 31, 1899January 1, 1900
59February 28, 1900February 27, 1900February 28, 1900
60February 29, 1900 (never existed)February 28, 1900null
61March 1, 1900March 1, 1900March 1, 1900
40729July 5, 2011July 5, 2011July 5, 2011

Counting from December 30, 1899 is right from March 1, 1900 on, and a day early before it. This version, from our test script, handles both:

function excelSerialToDate(serial) {
  if (serial === 60) return null; // February 29, 1900: a day only Excel has
  const start = serial < 60 ? Date.UTC(1899, 11, 31) : Date.UTC(1899, 11, 30);
  return new Date(start + serial * 86400000).toISOString().slice(0, 10);
}

A workbook on the 1904 date system numbers the same day 1,462 lower, Microsoft says: July 5, 2011 is 39267 there.

The other date trap is the time zone. MDN's Date.parse page says a date-only string like "2026-11-06" is read as UTC, "because it's date-only". In our test, new Date("2026-11-06") shown in Chicago's time zone read 11/5/2026. Ask the AI to keep dates as year, month, and day numbers, or to show them with timeZone: "UTC", and put a date near midnight and one before March 1, 1900 (if your sheet can have one) in the test table.

Paste the cases into the page: a hidden test mode

Typing 20 cases into a phone is where people stop testing. A test mode built into the page runs them for you. Paste the test rows (from the first input to the last expected value) after this, and ask the AI:

Add a test mode to the calculator. It opens when the address ends in #test,
also when #test is added after the page has loaded.
- Write the test rows below into the file and run them when the test mode opens,
  so it works on a phone with nothing to paste.
- Show a text box for more rows copied from Excel: the inputs in the page's order,
  then the expected outputs. Cells are separated by tabs (or by spaces if there are
  no tabs). An empty cell is an empty box, a number with % is that number
  (7.5% means 7.5), and commas inside numbers are ignored.
- For each row, run the same functions the page uses (no copy of them), and show a table:
  each output, the expected value, the difference, and PASS or FAIL.
- PASS when the values match after rounding both to the decimals the page shows.
  For a value the page doesn't round, PASS when the difference is under 1e-9 times
  the expected value, or under 1e-9 when the value is below 1.
- Show the intermediate values for any row that fails.
- Keep the normal page unchanged when the address has no #test.
Test rows: [paste them here]

The point of "no copy of them" is that the test runs the code people use, not a second version of it. A separate test page would need its own copy of the functions, and two copies drift apart.

Run it on your computer first. Open the HTML file in your computer's browser, add #test to the end of the address in the address bar, and press Enter (reload the page if the test mode doesn't appear). The rows written into the file run, and you can paste more straight from Excel. That's where the calculator first runs, before you upload anything.

In our test on November 6, 2026, a concrete order calculator built this way passed all 4 outputs of its 8 rows in headless Chromium at 390 pixels wide: opened with #test, from the file on the computer, with the rows pasted as tab-separated text with the waste as "5%" and one cell empty, with 3 rows separated by spaces, and with #test added after the page had loaded. A 9th row with a wrong expected value showed FAIL, with the page's value and the expected one side by side.

Then on a phone. The page needs an address. Drop the file in the box at the top of this page: its preview link runs no scripts, so click Keep this page — free, no card and sign up, and the page's scripts run in your account. Publish it, then open the address under Live URL on the phone with #test at the end. The rows in the file run by themselves; for other rows, email them to yourself and copy them from the email (a row with an empty cell needs its tabs, so check that it still lines up). The part after # stays in the browser, so the test mode never changes what other visitors see. If the cases hold a client's figures, keep them out of the file and paste them instead: anyone who opens the page can read its source.

Read a mismatch from the intermediate values

  1. Check the inputs first. Millimetres typed where the page wants metres, 5 typed where it wants 0.05, a blank box the page reads as 0.
  2. Walk the intermediate values in calculation order. The first one that differs is where the bug is; everything after it is a consequence. For that cell, Excel's Formulas > Evaluate Formula shows "the different parts of a nested formula evaluated in the order the formula is calculated".
  3. Look at the size of the difference. It usually names the cause:
What the difference looks likeLikely causeWhat to change
In the 15th digit or beyond (1e-15 of the value)Floating point, as in ExcelThe comparison: use the tolerance
Exactly one step of the last decimal, on a halfROUND versus Math.round or toFixedUse excelRound
One step of a CEILING or ROUNDUPA value like 27.500000000000004Make the page do what the sheet's row shows: if the sheet gives 27.5, round to 15 significant digits before rounding up
A factor of 100, 1000, 25.4, or 3.28A percent or a unit read the wrong wayThe input's label and its conversion
A different answer only near a threshold> in one, >= in the otherThe IF boundary
A whole row's value from a neighbouring rowApproximate lookup on an unsorted table, or the wrong match typeSort the table, or match exactly
A solver's answer a few units off in the 4th digitA different stopping toleranceState the tolerance in both
A date one day offThe 1900 leap day, or UTC versus local timeThe date conversion above
  1. Give the AI both numbers. "For these inputs, the sheet gives 27.5 in B9 and the page gives 28. Here is the cell's formula and the page's function. Explain the difference, change only that function, and don't change any other formula."
  2. Decide which side is wrong. Sometimes the test finds a quirk in the sheet, such as a formula that returns a load for zero trucks. Fix it in the sheet and the page together, and keep the case in the table.

Keep the test with the page, and run it at every version

  • The cases live in the workbook. After a change to the sheet, bring the Tests sheet's expected values up to date (copy the formulas across again, or paste the new values), then copy the cells from the first input to the last expected value. Give them to the AI with the change, so the new file carries the new rows, and run its #test on your computer.
  • A new version gets the same test before it goes live. On Convika, open the page's screen, and under Update from an HTML file, click Upload a new version, choose the corrected file, and click Upload as a new version. Click Open preview, then Open in a new tab, add #test to the end of the address, and reload the page. The preview link works for 3 minutes; if it has ended by the time you reload, click Open preview and Open in a new tab again. Only when every row passes, click Publish v2 at the same link (with your version number). Everyone with the link, a home screen icon, or a printed QR code gets the new version at the same address.
  • The version number is on the page. Put it in the footer, next to the date, and in the workbook's Tests sheet, so an answer someone screenshots can be traced to its version.
  • Old versions stay for a while. Free keeps the last 10 versions of a page and Pro the last 50. If a published version turns out wrong, roll back to the last one that passed: see how to update an AI-made page without changing its URL.

What a passing test tells you, and what it doesn't

A full pass shows that the page gives the sheet's answers for the cases you tried. It doesn't show that the sheet is right, that the formula suits the job, or that a case you didn't try works. Put the method, the units, and the range the formula holds for on the page itself, next to the result, so whoever uses it can see what it assumes. You stay responsible for checking the results against your own standard or code.

Frequently asked questions

How do I check that a calculator ChatGPT wrote from my spreadsheet gives the same results as Excel?

Run the same 10 to 20 input sets through both and compare every output, intermediate values included, to a tolerance you set first. Take real jobs, then add a zero, a blank, the limits, a rounding half, and each side of every IF. Paste the rows into a test mode in the page, so the test runs the page's own code.

Is it safe to use an AI-generated engineering calculator for work?

Only after it matches your sheet, or your hand calculation, on every case you'd stake the result on, and only for what the formula is meant for. A passing test shows the page reproduces the sheet; whether the sheet's method fits your job is still your engineering judgement. Show the method, the units, and the range of validity on the page, and test again at every new version.

Why does my JavaScript calculator round differently from Excel?

Because Excel's ROUND rounds halves away from zero, and JavaScript's Math.round rounds them toward +∞. Microsoft's own example, =ROUND(-1.475, 2), gives -1.48 in Excel and -1.47 with Math.round. toFixed differs too: it gives "2.1" for 2.15, where Excel gives 2.2. Use a function that rounds the 15-digit value away from zero.

Why does the page show 0.30000000000000004 or -2.220446049250313e-16?

Because JavaScript prints up to 17 significant digits, and Excel shows 15. Both store the same binary numbers, which can't hold 0.1 exactly. Excel since Excel 97 also shows 0 for a sum that lands very close to zero. Show results with the sheet's decimals, and compare with a tolerance instead of ===.

How many test cases do I need?

10 to 20 is enough for most calculators: a handful of real jobs, plus one case for each edge and each branch. A sheet with many IFs or lookup tables needs more, because each branch and each table boundary needs its own case. What matters is that every path through the formulas runs at least once.

What tolerance should I use when comparing with Excel?

For a result shown to N decimals, an exact match after rounding both to N decimals. For an unrounded value, a relative difference under 0.000000001. For Goal Seek or IRR, the tolerance you gave the solver. Set it before you run the cases, so a failure can't be argued away afterwards.

Why is a date one day off between Excel and the page?

Usually for one of two reasons. Excel treats 1900 as a leap year, so a conversion that counts days from December 30, 1899 is right from March 1, 1900 but a day early before it. Or the page read a date-only string as UTC midnight and showed it in local time, which is the day before west of UTC.

Can ChatGPT check its own calculator against my sheet?

It can list the formulas it wrote and suggest test cases, which helps. The expected values have to come from your sheet, though, not from the AI: otherwise you're testing the page against the AI's idea of the sheet. Paste Excel's results into the page's test mode, and give the AI both numbers when a case fails.

Sources

Next step

How to password protect an HTML page without code, on your own domain

JavaScript passwords sit in the page code. Put an HTML page from ChatGPT or Claude behind a server-checked password on your own domain.

Related articles

More calculators built from Excel sheets

AI Skill Pod

Share AI skills with your team, the easy way

Everyone uses your team's skills in their own ChatGPT, Claude or Gemini, on any plan. Send one invite link. Free to start.

Start free on AI Skill Pod⁠

AI Skill Pod is made by the team behind Convika.

Share this article

Test the calculator on the phones that will use it

Publish the AI's HTML file, open its link with #test on a phone, and the test rows in the file run there. Every new version goes live at the same address.

Get a link for my calculator

Free plan: no credit card, 1 published page. A private link or a password comes with Pro, $12 a month.