Financial functions

RRI

Refuses 45 of 5,533 recorded calls; the rest match

Of 5,533 recorded answers (5,528 in the answer bank and 5 workbook cells), 45 do not match: 45 are refused. How we measure this · See the Rust code

Local names in 40 languages
LanguageName in Excel
ArabicRRI
BulgarianRRI
CzechRRI
DanishRRI
GermanRRI
GreekRRI
English (Australia)RRI
English (United Kingdom)RRI
English (United States)RRI
SpanishRRI
EstonianRRI
FinnishTOT.ROI
FrenchTAUX.INT.EQUIV
HebrewRRI
CroatianRRI
HungarianMR
IndonesianRRI
ItalianRRI
JapaneseRRI
KoreanRRI
LithuanianRRI
LatvianRRI
NorwegianREALISERT.AVKASTNING
DutchRRI
PolishRÓWNOW.STOPA.PROC
Portuguese (Brazil)RRI
Portuguese (Portugal)DEVOLVERTAXAJUROS
RomanianRRI
RussianЭКВ.СТАВКА
SlovakRRI
SlovenianRRI
Serbian (Latin)RRI
SwedishAVKPÅINVEST
ThaiRRI
TurkishGERÇEKLEŞENYATIRIMGETİRİSİ
UkrainianRRI
VietnameseRRI
Chinese (Simplified)RRI
Chinese (Hong Kong)RRI
Chinese (Traditional)RRI

Names from Microsoft's support site.

What it does

RRI(nper, pv, fv)

RRI(nper,pv,fv) returns the equivalent compound rate per period between a starting and final amount, without intermediate cash flows. Mathematically it is (fv/pv)^(1/nper)-1.

Try it

Input cells (optional)

Example: {"B2": 3, "B3": 4}. A1 holds the formula. Other cells need values before a formula can read them.

Enter a formula, then calculate.

Runs locally in your browser with OneCalc. Its answer may differ from Excel. Use English function names and commas between arguments.

=RRI(2,64,100) returns about 0.25: the growth factor is 1.5625, whose square root is 1.25. Two periods compound that rate from 64 to 100.

Quirks

The recorded current kernel rejects nonpositive or subnormal period counts before its equality shortcut. It normalises subnormal value inputs to zero, checks equal values before sign guards, and admits two negative amounts with a positive ratio. A zero present value or opposite nonzero signs gives #NUM! under those rules.

How to implement

Use stored x87 division for base=fv/pv and for reciprocal=1/nper. A normalised zero base returns minus one. For exactly one period, retain the quotient directly as the powered value; otherwise use the raw measured LN/product/EXP power chain, not the worksheet POWER square-root shortcut. Store the final subtraction of one. The current helper also applies finite-result guards. This preserves cancellation-sensitive stores near equal amounts; native pow followed by subtraction can differ substantially on small rates.

Rust code

Show the CalcFunc source of this function

Quoted from the public repository DnaCalc/DnaCalc, crates calc-func and calc-fml, at commit 9e1884369a67. Comments are the source's own. A kernel shared with other functions appears once, on its module page.

RRI · 3 lines · calc-func/src/catalogue/financial.rs on GitHub
13 rri_fn "RRI" (3, 3) [V "nper", V "pv", V "fv"] |s, a, sv| {
    tv_out(s, tv::rri(num(s, a, 0)?, num(s, a, 1)?, num(s, a, 2)?))
}
financial_daz · 8 lines · calc-func/src/ported/financial_time_value_family.rs on GitHub
#[inline]
fn financial_daz(value: f64) -> f64 {
    if value.abs() < f64::MIN_POSITIVE {
        0.0_f64.copysign(value)
    } else {
        value
    }
}
rri · 62 lines · calc-func/src/ported/financial_time_value_family.rs on GitHub
pub fn rri(periods: f64, present_value: f64, future_value: f64) -> Result<f64, FinancialError> {
    validate_finite(&[periods, present_value, future_value])?;
    // W109's live edge-domain batteries pin the guard order as tightly as the
    // positive-domain power graph. Positive subnormal periods are rejected
    // before the equality shortcut, while MIN_POSITIVE is admitted.
    if periods < f64::MIN_POSITIVE {
        return Err(FinancialError::Num);
    }

    // This legacy financial body observes DAZ-normalized value inputs.
    // Equality precedes the sign guards, so equal zeros/subnormals (and even
    // equal negative normal values) publish +0.
    let present_value = financial_daz(present_value);
    let future_value = financial_daz(future_value);
    if present_value == future_value {
        return Ok(0.0);
    }
    // A present value of 0 and values of opposite signs are #NUM!; two negative values have a
    // positive ratio and are computed like positive ones (dc-ifc, Excel 16.0.20430 on 2026-10-27:
    // RRI(1,-1,-3) is 2, RRI(2,-4,-9) 0.5, RRI(2,-5,0) and RRI(2,5,0) -1, RRI(2,0,5),
    // RRI(2,-5,5) and RRI(2,5,-5) #NUM!).
    let opposite = (present_value < 0.0) != (future_value < 0.0) && future_value != 0.0;
    if present_value == 0.0 || opposite {
        return Err(FinancialError::Num);
    }

    // W109 G6-13 / BUG-FUNC-044: RRI is a legacy x87 spill body. Its wrapper
    // division, reciprocal, and final subtraction are each RN53(RN64(op)); the
    // power itself is the raw x87 chain
    // `exp(RN53(RN64((1/n) * ln(base))))`. Native `powf` misses the near-one
    // cancellation ladder by 2^27 output ULP, and `ln(base)/n` misses 97 of the
    // fresh 4,900 rows. This is NOT the worksheet POWER wrapper: RRI(2,1,2)
    // takes the raw chain and bypasses POWER's exponent-0.5 sqrt shortcut.
    // The published quotient is DAZ-normalized too. Its zero lane is exactly
    // -1 and must bypass the raw LN/EXP helper, whose contract requires a
    // finite positive base.
    let base = financial_daz(excel_x87_div(future_value, present_value));
    if base == 0.0 {
        return Ok(-1.0);
    }
    if !base.is_finite() {
        return Err(FinancialError::Num);
    }
    let reciprocal = excel_x87_recip(periods);
    if !reciprocal.is_finite() {
        return Err(FinancialError::Num);
    }

    // periods==1 is an exact identity route, not merely an exponent that
    // happens to equal one. Adjacent binary64 period values take the raw chain.
    let powered = if periods == 1.0 {
        base
    } else {
        excel_pow_chain(base, reciprocal)
    };
    let result = excel_x87_sub(powered, 1.0);
    if result.is_finite() {
        Ok(result)
    } else {
        Err(FinancialError::Num)
    }
}

Kernels shared with other functions

Argument and result plumbing

  • fail catalogue/kit
  • num catalogue/kit

No implementation has been published with a Handbook test suite for this function.

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.

Excel 16.0 buildPlatform and CPUCaptured inputs
20228Windows, 64-bit, CPU not recorded5,367

The 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.

Recorded environments and comparison details.

Excel 16.0 build 20228

Windows, 64-bit, CPU not recorded

5,367 captured inputs are indexed for this environment. Capture dates: 2026-08-09 to 2026-08-09. This is a reading count, not a comparison with another build.

Alternatives

PDURATION solves periods; RATE includes constant payments; XIRR includes dated cash flows.

Named variants

No named variants are recorded yet.

Suggest a correction or contribute an implementation · For agents