Namensräume
Varianten
Aktionen

std::lerp

Von cppreference.com
< cpp‎ | numeric
 
 
 
Definiert in der Header-Datei <cmath>
(1)
constexpr float       lerp( float a, float b, float t ) noexcept;

constexpr double      lerp( double a, double b, double t ) noexcept;
constexpr long double lerp( long double a, long double b,

                            long double t ) noexcept;
(seit C++20)
(bis C++23)
constexpr /* gleitkommazahl-Typ */

    lerp( /* gleitkommazahl-Typ */ a,
          /* gleitkommazahl-Typ */ b,

          /* gleitkommazahl-Typ */ t ) noexcept;
(seit C++23)
Definiert in der Header-Datei <cmath>
template< class Arithmetic1, class Arithmetic2, class Arithmetic3 >

constexpr /* gemeinsamer-gleitkommazahl-Typ */

    lerp( Arithmetic1 a, Arithmetic2 b, Arithmetic3 t ) noexcept;
(A) (seit C++20)
1) Berechnet die lineare Interpolation zwischen a und b, wenn der Parameter t innerhalb von [01) liegt (andernfalls lineare Extrapolation), d.h. das Ergebnis von a+t(b−a) unter Berücksichtigung von Ungenauigkeiten bei der Gleitkomma-Berechnung. Die Bibliothek stellt Überladungen für alle cv-unqualifizierten Gleitkommatypen als Typen der Parameter a, b und t bereit.(seit C++23)
A) Zusätzliche Überladungen werden für alle anderen Kombinationen von arithmetischen Typen bereitgestellt.

Inhalt

[edit] Parameter

a, b, t - Gleitkomma- oder Ganzzahlwerte

[edit] Rückgabewert

a + t(b − a)

Wenn std::isfinite(a) && std::isfinite(b) true ist, sind die folgenden Eigenschaften garantiert

  • Wenn t == 0, ist das Ergebnis gleich a.
  • Wenn t == 1, ist das Ergebnis gleich b.
  • Wenn t >= 0 && t <= 1, ist das Ergebnis endlich.
  • Wenn std::isfinite(t) && a == b, ist das Ergebnis gleich a.
  • Wenn std::isfinite(t) || (b - a != 0 && std::isinf(t)), ist das Ergebnis nicht NaN.

Sei CMP(x, y) 1, wenn x > y, -1, wenn x < y, und 0 andernfalls. Für beliebige t1 und t2 ist das Produkt aus

  • CMP(std::lerp(a, b, t2), std::lerp(a, b, t1)),
  • CMP(t2, t1) und
  • CMP(b, a)

nicht-negativ. (Das heißt, std::lerp ist monoton.)

[edit] Anmerkungen

Die zusätzlichen Überladungen müssen nicht exakt wie in (A) angegeben bereitgestellt werden. Sie müssen nur ausreichen, um sicherzustellen, dass für ihr erstes Argument num1, zweites Argument num2 und drittes Argument num3

  • Wenn num1, num2 oder num3 den Typ long double hat, dann hat std::lerp(num1, num2, num3) denselben Effekt wie std::lerp(static_cast<long double>(num1),
              static_cast<long double>(num2),
              static_cast<long double>(num3))
    .
  • Andernfalls, wenn num1, num2 und/oder num3 den Typ double oder einen ganzzahligen Typ haben, dann hat std::lerp(num1, num2, num3) denselben Effekt wie std::lerp(static_cast<double>(num1),
              static_cast<double>(num2),
              static_cast<double>(num3))
    .
  • Andernfalls, wenn num1, num2 oder num3 den Typ float hat, dann hat std::lerp(num1, num2, num3) denselben Effekt wie std::lerp(static_cast<float>(num1),
              static_cast<float>(num2),
              static_cast<float>(num3))
    .
(bis C++23)

Wenn num1, num2 und num3 arithmetische Typen haben, dann hat std::lerp(num1, num2, num3) denselben Effekt wie std::lerp(static_cast</*gemeinsamer-gleitkommazahl-Typ*/>(num1),
          static_cast</*gemeinsamer-gleitkommazahl-Typ*/>(num2),
          static_cast</*gemeinsamer-gleitkommazahl-Typ*/>(num3))
, wobei /*gemeinsamer-gleitkommazahl-Typ*/ der Gleitkommatyp mit dem höchsten Gleitkomma-Konvertierungsrang und dem höchsten Gleitkomma-Konvertierungs-Subrang unter den Typen von num1, num2 und num3 ist. Argumente vom ganzzahligen Typ werden so betrachtet, als hätten sie denselben Gleitkomma-Konvertierungsrang wie double.

Wenn kein solcher Gleitkommazahltyp mit dem höchsten Rang und Subrang existiert, dann führt die Überladungsauflösung nicht zu einem nutzbaren Kandidaten aus den bereitgestellten Überladungen.

(seit C++23)
Feature-Test-Makro Wert Std Feature
__cpp_lib_interpolate 201902L (C++20) std::lerp, std::midpoint

[edit] Beispiel

#include <cassert>
#include <cmath>
#include <iostream>
 
float naive_lerp(float a, float b, float t)
{
    return a + t * (b - a);
}
 
int main()
{
    std::cout << std::boolalpha;
 
    const float a = 1e8f, b = 1.0f;
    const float midpoint = std::lerp(a, b, 0.5f);
 
    std::cout << "a = " << a << ", " << "b = " << b << '\n'
              << "midpoint = " << midpoint << '\n';
 
    std::cout << "std::lerp is exact: "
              << (a == std::lerp(a, b, 0.0f)) << ' '
              << (b == std::lerp(a, b, 1.0f)) << '\n';
 
    std::cout << "naive_lerp is exact: "
              << (a == naive_lerp(a, b, 0.0f)) << ' '
              << (b == naive_lerp(a, b, 1.0f)) << '\n';
 
    std::cout << "std::lerp(a, b, 1.0f) = " << std::lerp(a, b, 1.0f) << '\n'
              << "naive_lerp(a, b, 1.0f) = " << naive_lerp(a, b, 1.0f) << '\n';
 
    assert(not std::isnan(std::lerp(a, b, INFINITY))); // lerp here can be -inf
 
    std::cout << "Extrapolation demo, given std::lerp(5, 10, t):\n";
    for (auto t{-2.0}; t <= 2.0; t += 0.5)
        std::cout << std::lerp(5.0, 10.0, t) << ' ';
    std::cout << '\n';
}

Mögliche Ausgabe

a = 1e+08, b = 1
midpoint = 5e+07
std::lerp is exact?: true true
naive_lerp is exact?: true false
std::lerp(a, b, 1.0f) = 1
naive_lerp(a, b, 1.0f) = 0
Extrapolation demo, given std::lerp(5, 10, t):
-5 -2.5 0 2.5 5 7.5 10 12.5 15

[edit] Siehe auch

(C++20)
Mittelpunkt zwischen zwei Zahlen oder Zeigern
(Funktionstemplate) [bearbeiten]