{
  "category": "Statistical functions",
  "display_name": "FORECAST",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.FORECAST",
  "implementation_state": {
    "answer_bank": {
      "excel_builds": [
        "20131"
      ],
      "larger_numeric": 0,
      "last_bit": 0,
      "matched": 70,
      "other_mismatch": 0,
      "refused": 0,
      "rows": 70,
      "unread": 0,
      "worst_ulp": 0
    },
    "detail": "Recorded: 70 in the answer bank and 8 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 78 recorded answers",
    "workbook_corpus": {
      "cells": 8,
      "matched": 8
    }
  },
  "implementations": [
    {
      "commit": "9e1884369a678158dd82d3d74188daf986995e87",
      "flavour": "excel-compatibility-candidate",
      "language": "Rust",
      "name": "CalcFunc",
      "own_code": [
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/statistics.rs#L380-L383"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/statistics::forecast"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/statistics.rs#L380-L383",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 78 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.FORECAST.json",
  "name": "FORECAST",
  "notes": [],
  "schema": "efh.function-reference/v1",
  "section_order": [
    "what-it-does",
    "try-it",
    "quirks",
    "how-to-implement",
    "version-differences",
    "alternatives"
  ],
  "sections": {
    "alternatives": "\n### Relationships\n\n- **`TREND`** — the array-valued generalisation: multiple predictors, multiple evaluation\n  points, one call. `FORECAST` is `TREND` restricted to one predictor and one point, *as\n  mathematics*. Upstream's record is explicit that it is not the same code path in Excel; see\n  **What has not been checked**.\n- **`SLOPE` and `INTERCEPT`** — the two halves of the same fit, exposed separately.\n  `SLOPE(y,x)*x0 + INTERCEPT(y,x)` is `FORECAST(x0,y,x)` mathematically, and is a different\n  arithmetic expression, so agreement in the last bit is not to be assumed.\n- **`LINEST`** — the full regression report. Excel's own `FORECAST` is documented by upstream\n  as *not* running the `LINEST` pipeline.\n- **`FORECAST.ETS` family** — exponential-smoothing time-series forecasting. Same first word,\n  entirely different method; a reader looking for seasonality wants those, not this.\n- **`GROWTH`** — the exponential analogue, fitted in log-space.\n\n\n",
    "how-to-implement": "\n### Numerical notes\n\n\n**Centered versus raw sums.** The slope can be computed two ways that are algebraically\nidentical and numerically nothing alike:\n\n    centered:  Σ(xᵢ − x̄)(yᵢ − ȳ) / Σ(xᵢ − x̄)²\n    raw:       (nΣxᵢyᵢ − ΣxᵢΣyᵢ) / (nΣxᵢ² − (Σxᵢ)²)\n\nThe raw form is the one in most textbooks and most first implementations, and it is a\ncatastrophic-cancellation machine: when the xᵢ share a large offset — Excel date serials,\ntimestamps, anything with five significant digits before the interesting ones start —\n`nΣxᵢ²` and `(Σxᵢ)²` are enormous and nearly equal, and their difference retains only the\nlow-order digits that survived rounding. The relative error grows like the square of the ratio\nof the mean to the spread. This is the standard result and it is why the centered form, or a\nWelford-style updating formula, is the right choice. Björck's treatment of the normal equations\nis the reference; the same lesson governs `VAR.S` and `STDEV.S`.\n\nThe two-pass centered form needs the mean before the deviations, so it reads the data twice.\nThat is a real cost only for very long ranges, and it buys a conditioning improvement that no\namount of care in the raw form can recover.\n\n**What upstream identified for Excel.** The evidence record attached to this page states a\nstructural conclusion: Excel's `FORECAST` is *not* the `LINEST` pipeline but a centered\nplain-double kernel — forward sums to means, one fused loop accumulating both the covariance\nand the variance, and publication in the intercept form a + b·x. That identification is\nupstream's, it names its own corpus, and the corpus was built alongside the hypothesis rather\nthan held out — the record says so in as many words. It is a strong structural claim with a\nweak-blindness caveat, and both halves travel together.\n\n**Why the fused loop matters.** Accumulating Σ(xᵢ − x̄)(yᵢ − ȳ) and Σ(xᵢ − x̄)² in the same\npass, in the same order, with the same intermediate precision, is a different rounding sequence\nfrom computing them in two loops — even though it is the same mathematics. For a\ncompatibility-oriented implementation the loop structure is part of the specification, not an\noptimisation detail.\n\n**The evaluation step.** Publishing as `a + b·x` rather than as `ȳ + b·(x − x̄)` is another\nchoice that changes the last bits, and the two are not interchangeable for compatibility even\nthough they agree mathematically. The centered evaluation form is more accurate; the intercept\nform is what upstream identifies.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns `Number` — a scalar, never an array.\n\n- **Two points** is the smallest fit with a defined slope, and it reproduces the line through\n  them exactly (subject to rounding).\n- **One point**, or any input where all xᵢ coincide, has a zero denominator. Documented:\n  `#DIV/0!`.\n- **Constant y, varying x** is fine: slope 0, intercept ȳ.\n- **Length mismatch** between the two vectors is documented as `#N/A`.\n- **Empty inputs** are documented as `#N/A` too — and here the documentation and the reference\n  engine part company. See **Errors**.\n- **Large common offsets** in x (dates are the everyday example: five-digit serial numbers with\n  a one-digit spread) are the classic accuracy hazard for this function and are discussed\n  under **Numerical notes**.\n- **Arrays** are consumed as data, not lifted. `FORECAST` never spills.\n\n\n\n### Errors\n\n\nAs documented by Microsoft on the VBA reference page for this method:\n\n| Error | Condition |\n|---|---|\n| `#VALUE!` | `x` is nonnumeric |\n| `#N/A` | `known_y's` and `known_x's` are empty, or contain a different number of data points |\n| `#DIV/0!` | the variance of `known_x's` equals zero |\n\nErrors inside the scanned ranges propagate under the shared coercion discipline.\n\n\n",
    "sources": "- Microsoft Learn, \"WorksheetFunction.Forecast_Linear method (Excel)\" — the replacement\n  surface, whose Remarks are near-identical in wording.\n- Handbook evidence record `EV-MISC-0007` — the structural identification of Excel's kernel\n  and the corpus caveats stated above. The record's own figures render mechanically beside this\n  page; the prose deliberately does not restate them.\n- Å. Björck, *Numerical Methods for Least Squares Problems* — conditioning of the normal\n  equations, the basis for the centered-versus-raw discussion.\n- Handbook, [Coercion and lifting](../model/02-coercion-and-lifting.md) — scan versus direct\n  argument policy and error propagation.\n- Handbook projections `data/functions/FUNC.FORECAST.json` (arity, category, custom coercion\n  and kernel classes) and `data/presence/FUNC.FORECAST.json` (the shared\n  `regression_forecast_family` module, held jointly with `FORECAST.LINEAR`, `GROWTH`, `LINEST`,\n  `LOGEST` and `TREND`).\n\n\n",
    "version-differences": "The recorded environments below distinguish a reading from a same-input comparison. Counts describe captured inputs in each environment; overlapping captures and comparisons are not totals of unique worksheet calls.\n\n| Excel 16.0 build | Platform and CPU | Captured inputs |\n|---|---|---:|\n| 20131 | Windows, bitness not recorded, AMD Ryzen 7 4800H with Radeon Graphics | 70 |\n\nThe record contains no same-input comparison between these environments. Reading different inputs on different builds does not establish either a version change or cross-build agreement.\n\n[Recorded environments and comparison details](https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.FORECAST.json).",
    "what-it-does": "\n`FORECAST(x, known_ys, known_xs)` fits a straight line to the paired data by ordinary least\nsquares and evaluates that line at `x`. Microsoft gives the model in exactly this form: the\nequation is **a + bx**, where a is the intercept and b the slope, and where the sample means\nare `AVERAGE(known_x's)` and `AVERAGE(known_y's)`.\n\nWritten out, with n paired observations (xᵢ, yᵢ) and means x̄, ȳ:\n\n    b  =  Σ (xᵢ − x̄)(yᵢ − ȳ)  /  Σ (xᵢ − x̄)²\n    a  =  ȳ − b·x̄\n    FORECAST(x, …)  =  a + b·x\n\nThree things are worth reading off that definition rather than assuming them.\n\n**It is a fit, not an interpolation.** `FORECAST` does not pass through the data points and has\nno notion of \"nearest observation\". If the requested `x` coincides with an observed xᵢ, the\nanswer is the fitted value at that abscissa, not yᵢ.\n\n**There is no extrapolation guard.** The formula is evaluated at whatever `x` is given, inside\nor outside the observed range. The word \"forecast\" in the name is a statement about intent, not\nabout a check the function performs.\n\n**The denominator is the sum of squared deviations of x.** It vanishes exactly when every xᵢ is\nidentical — a vertical scatter with no leverage — and that is the case Microsoft documents as\n`#DIV/0!`. It does not vanish when the *y*s are constant: a constant y with varying x is a\nperfectly well-posed fit with slope zero.\n\nThe quantity b is also, up to scaling, the covariance over the variance: b = cov(x, y)/var(x)\nwith matching denominators, which is why `SLOPE`, `COVARIANCE.P`/`COVARIANCE.S`, and `CORREL`\nall compute pieces of the same sum and why an implementation that shares those pieces is\ntempting and dangerous — see **Numerical notes**.\n\n\n\n### Arguments\n\n| Argument | Meaning |\n|---|---|\n| `x` | The abscissa at which to evaluate the fitted line. Documented as \"the data point for which you want to predict a value\". |\n| `known_y's` | The dependent array or range. |\n| `known_x's` | The independent array or range. |\n\n`x` is a scalar numeric slot; the two data arguments are vector-shaped and consumed by\nscanning rather than by elementwise lifting — this is not a lift kernel. Which values a scan\nadmits and which it skips is family policy, not engine law; see\n[Coercion and lifting](../model/02-coercion-and-lifting.md).\n\nThe pairing is positional. Nothing checks that the two vectors are *meaningfully* paired; the\nonly check documented is that they contain the same number of data points.\n\n\n"
  },
  "signature": {
    "display": "FORECAST(x, known_ys, known_xs)",
    "parameters": [
      {
        "description": null,
        "name": "x",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "known_ys",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "known_xs",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 3,
        "min": 3
      },
      "category": "Statistical functions",
      "classification": {
        "arg_preparation_profile": "RefsVisibleInAdapter",
        "coercion_lift_profile": "Custom",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "None",
        "fec_dependency_profile": "RefOnly",
        "host_interaction_class": "None",
        "kernel_signature_class": "Custom",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": null,
        "short": "Value predicted for x on the least-squares line through the known points",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns a value along a linear trend",
        "microsoft_url": "https://support.microsoft.com/en-us/office/forecast-and-forecast-linear-functions-50ca49c9-7b40-4892-94e4-7ad38bbeda99"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "FORECAST"
        },
        {
          "locale": "bg-BG",
          "name": "FORECAST"
        },
        {
          "locale": "cs-CZ",
          "name": "FORECAST"
        },
        {
          "locale": "da-DK",
          "name": "PROGNOSE"
        },
        {
          "locale": "de-DE",
          "name": "FORECAST"
        },
        {
          "locale": "el-GR",
          "name": "FORECAST"
        },
        {
          "locale": "en-AU",
          "name": "FORECAST"
        },
        {
          "locale": "en-GB",
          "name": "FORECAST"
        },
        {
          "locale": "en-US",
          "name": "FORECAST"
        },
        {
          "locale": "es-ES",
          "name": "PRONOSTICO"
        },
        {
          "locale": "et-EE",
          "name": "FORECAST"
        },
        {
          "locale": "fi-FI",
          "name": "ENNUSTE"
        },
        {
          "locale": "fr-FR",
          "name": "PREVISION*"
        },
        {
          "locale": "he-IL",
          "name": "FORECAST"
        },
        {
          "locale": "hr-HR",
          "name": "FORECAST"
        },
        {
          "locale": "hu-HU",
          "name": "ELŐREJELZÉS"
        },
        {
          "locale": "id-ID",
          "name": "FORECAST"
        },
        {
          "locale": "it-IT",
          "name": "FORECAST"
        },
        {
          "locale": "ja-JP",
          "name": "FORECAST"
        },
        {
          "locale": "ko-KR",
          "name": "FORECAST"
        },
        {
          "locale": "lt-LT",
          "name": "FORECAST"
        },
        {
          "locale": "lv-LV",
          "name": "FORECAST"
        },
        {
          "locale": "nb-NO",
          "name": "PROGNOSE"
        },
        {
          "locale": "nl-NL",
          "name": "VOORSPELLEN"
        },
        {
          "locale": "pl-PL",
          "name": "REGLINX"
        },
        {
          "locale": "pt-BR",
          "name": "PREVISÃO"
        },
        {
          "locale": "pt-PT",
          "name": "PREVISÃO"
        },
        {
          "locale": "ro-RO",
          "name": "FORECAST"
        },
        {
          "locale": "ru-RU",
          "name": "ПРЕДСКАЗ"
        },
        {
          "locale": "sk-SK",
          "name": "PREDPOVEĎ:"
        },
        {
          "locale": "sl-SI",
          "name": "FORECAST"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "FORECAST"
        },
        {
          "locale": "sv-SE",
          "name": "PREDIKTION"
        },
        {
          "locale": "th-TH",
          "name": "FORECAST"
        },
        {
          "locale": "tr-TR",
          "name": "TAHMİN"
        },
        {
          "locale": "uk-UA",
          "name": "FORECAST"
        },
        {
          "locale": "vi-VN",
          "name": "FORECAST"
        },
        {
          "locale": "zh-CN",
          "name": "FORECAST"
        },
        {
          "locale": "zh-HK",
          "name": "FORECAST"
        },
        {
          "locale": "zh-TW",
          "name": "FORECAST"
        }
      ],
      "signature": {
        "display": "FORECAST(x, known_ys, known_xs)",
        "parameters": [
          {
            "description": null,
            "name": "x",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "known_ys",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "known_xs",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "FORECAST",
      "version_marker": null,
      "xlcall": {
        "code": "309",
        "symbol": "xlfForecast"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/forecast-and-forecast-linear-functions-50ca49c9-7b40-4892-94e4-7ad38bbeda99"
  },
  "try_it": {
    "formula": "=FORECAST(4,{2;4;6},{1;2;3})"
  },
  "url": "https://handbook.dnacalc.com/functions/FORECAST.html",
  "variants": [],
  "versions": [
    {
      "behaviour": "70 captured inputs are indexed for this environment. Capture dates: 2026-07-12 to 2026-07-12. This is a reading count, not a comparison with another build.",
      "excel_build": "16.0 build 20131",
      "platform": "Windows, bitness not recorded, AMD Ryzen 7 4800H with Radeon Graphics",
      "sources": [
        "https://github.com/DnaCalc/ExcelFunctionsHandbook/blob/5dc75391aa5125ccc5abdb095da85950980d6fd8/content/evidence/environments/FUNC.FORECAST.json"
      ]
    }
  ]
}