Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

ฟังก์ชัน acosh() ใน C++ STL (Inverse Hyperbolic Cosine)

acosh(x) หรือ Inverse Hyperbolic Cosine (Arc Hyperbolic Cosine) คืนค่า y ≥ 0 ที่ทำให้ cosh(y) = x

คุณสมบัติทางคณิตศาสตร์

  • Domain: x ∈ [1, +∞)
  • Range: y ∈ [0, +∞)
  • Function: Even-like (แต่ไม่ใช่ Even Function จริงๆ)
  • สูตร: acosh(x) = ln(x + √(x² - 1))
  • Derivative: d/dx acosh(x) = 1/√(x² - 1) (x > 1)

Syntax

#include <cmath>

double acosh(double x);
float acoshf(float x);
long double acoshl(long double x);

โค้ดตัวอย่างพื้นฐาน

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    double values[] = {1, 1.5, 2, 5, 10, 100};
    
    cout << "x\t\tacosh(x) (rad)\tacosh(x) (deg)" << endl;
    cout << "------------------------------------------" << endl;
    
    for (double x : values) {
        double rad = acosh(x);
        double deg = rad * 180 / M_PI;
        cout << x << "\t\t" << rad << "\t\t" << deg << endl;
    }
    
    // Domain Error Case
    double invalid = 0.5;
    double result = acosh(invalid);  // NaN
    cout << "\nacosh(0.5) = " << result << " (NaN - Domain Error)" << endl;
    
    return 0;
}

ผลลัพธ์

x		acosh(x) (rad)	acosh(x) (deg)
------------------------------------------
1		0			0
1.5		0.962424		55.14
2		1.31696		75.46
5		2.29243		131.34
10		2.99323		171.51
100		5.29829		303.57

acosh(0.5) = nan (Domain Error)

พฤติกรรมเมื่อ x ใหญ่ (Asymptotic)

acosh(x) ≈ ln(2x)  สำหรับ x >> 1

x = 1000:  acosh(1000) ≈ ln(2000) ≈ 7.6
x = 1e6:   acosh(1e6) ≈ ln(2e6) ≈ 14.5

Domain Error Handling


#include <iostream>
#include <cmath>
#include <cerrno>
#include <cfenv>
using namespace std;

int main() {
    double x = 0.5;
    
    // Method 1: Check errno
    errno = 0;
    double result = acosh(x);
    if (errno == EDOM) {
        cout << "Domain Error: x must be >= 1" << endl;
    }
    
    // Method 2: Check NaN
    if (isnan(result)) {
        cout << "Result is NaN" << endl;
    }
    
    // Method 3: Check before call
    if (x < 1) {
        cout << "Invalid input: " << x << " < 1" << endl;
    }
    
    return 0;
}

การประยุกต์ใช้

1. Special Relativity: Rapidity


// Lorentz Factor γ = cosh(rapidity)
// rapidity = acosh(γ)
double rapidityFromGamma(double gamma) {
    if (gamma < 1) return 0;  // Or handle error
    return acosh(gamma);
}

// Velocity from Rapidity
double velocityFromRapidity(double rapidity, double c = 1.0) {
    return c * tanh(rapidity);
}

2. Geometry: Hyperbolic Distance


// ระยะทางใน Hyperbolic Space (Poincaré Half-Plane Model)
// dist = acosh(1 + (dx² + dy²) / (2*y1*y2))
double hyperbolicDistance(double x1, double y1, double x2, double y2) {
    double dx = x2 - x1;
    double dy = y2 - y1;
    return acosh(1 + (dx*dx + dy*dy) / (2 * y1 * y2));
}

3. Catenary Curve (โค้งโซ่/สายไฟ)


// y = a * cosh(x/a)
// Inverse: x = a * acosh(y/a)
double catenaryX(double y, double a) {
    if (y < a) return 0;  // Below vertex
    return a * acosh(y / a);
}

4. Machine Learning: Loss Function


// acosh ใช้ในบาง Loss Functions ที่ต้องการ Penetration Margin
double marginLoss(double x, double margin = 1.0) {
    // x = similarity score
    // Want x >= margin
    if (x >= margin) return 0;
    return acosh(margin / x);  // Penalty
}

ความสัมพันธ์กับ Logarithm


#include <iostream>
#include <cmath>
using namespace std;

int main() {
    double x = 5.0;
    
    // Definition: acosh(x) = ln(x + √(x² - 1))
    double byAcosh = acosh(x);
    double byLog = log(x + sqrt(x*x - 1));
    
    cout << "acosh(" << x << ") = " << byAcosh << endl;
    cout << "ln(x + √(x²-1)) = " << byLog << endl;
    cout << "Difference: " << abs(byAcosh - byLog) << endl;
    
    return 0;
}

ผลลัพธ์

acosh(5) = 2.29243
ln(x + √(x²-1)) = 2.29243
Difference: 4.44e-16

Special Values

  • acosh(1) = 0
  • acosh(+∞) = +∞
  • acosh(x) สำหรับ x < 1 → NaN (Domain Error, errno = EDOM)
  • acosh(NaN) = NaN

Complex Version (C++11)


#include <complex>
#include <iostream>
using namespace std;

int main() {
    complex<double> z(0.5, 0);  // ในโดเมน Complex ได้ทุกค่า
    complex<double> result = acosh(z);
    cout << "acosh(0.5+0i) = " << result << endl;  // (0, 1.0472) ≈ i*π/3
    return 0;
}

สรุป Hyperbolic Functions ใน C++

Function Header Domain Range
sinh, cosh, tanh<cmath>ℝℝ / [1,∞) / (-1,1)
asinh<cmath>ℝℝ
acosh<cmath>[1,∞)[0,∞)
atanh<cmath>(-1,1)ℝ