最終更新日時(UTC): 2026年01月12日 03時53分40秒
teruyamato0731 が更新

履歴 編集

function
<cmath>

# std::copysign(C++11)

    namespace std {
      float
        copysign(float x,
                 float y);               // (1) C++11からC++20まで
      double
        copysign(double x,
                 double y);              // (2) C++11からC++20まで
      long double
        copysign(long double x,
                 long double y);         // (3) C++11からC++20まで

      constexpr floating-point-type
        copysign(floating-point-type x,
                 floating-point-type y); // (4) C++23

      Integral
        copysign(Integral x
                 Integral y);            // (5) C++11
      constexpr Integral
        copysign(Integral x
                 Integral y);            // (5) C++23

      float
        copysignf(float x,
                  float y);              // (6) C++17
      constexpr float
        copysignf(float x,
                  float y);              // (6) C++23

      long double
        copysignl(long double x,
                  long double y);        // (7) C++17
      constexpr long double
        copysignl(long double x,
                  long double y);        // (7) C++23
    }

## 概要

`x`の絶対値に`y`の符号が付いた値を生成する。

- (1) : `float`に対するオーバーロード
- (2) : `double`に対するオーバーロード
- (3) : `long double`に対するオーバーロード
- (4) : 浮動小数点数型に対するオーバーロード
- (5) : 整数型に対するオーバーロード (`double`にキャストして計算される)
- (6) : `float`型規定
- (7) : `long double`型規定

## 戻り値

`x`の絶対値に`y`の符号が付いた値を返す。

`x`の値がNaNである場合、`y`の符号が付いたNaNを返す。

## 備考

- 符号付きゼロを表現するが負のゼロを取り扱わない実装では、この関数はゼロを正と見なす。
- 浮動小数点数の符号ビットを検出したい場合は、`std::signbit`を使用できる。`NaN`の符号を検出できる移植性のある方法はこの2つのみである。
- C++23では、(1), (2), (3)が(4)に統合され、拡張浮動小数点数型を含む浮動小数点数型へのオーバーロードとして定義された

## 例

    #include <iostream>
    #include <cmath>
    #include <limits>

    int main()
    {
      // 通常の数値
      std::cout << "1.0f,  2.0f : " << std::copysign(1.0f, 2.0f) << std::endl;
      std::cout << "0.0f, -2.0f : " << std::copysign(0.0f, -2.0f) << std::endl;
      std::cout << "1.5f, -0.0f : " << std::copysign(1.5f, -0.0f) << std::endl;

      // 無限大
      const float inf = std::numeric_limits<float>::infinity();
      std::cout << "-inf,  3.0f : " << std::copysign(-inf, 3.0f) << std::endl;
      std::cout << "3.0f,  -inf : " << std::copysign(3.0f, -inf) << std::endl;

      // NaN (Not a Number)
      // NaNの符号もコピーされる。
      const float nan = std::numeric_limits<float>::quiet_NaN();
      std::cout << " nan, -4.2f : " << std::copysign(nan, -4.2f) << std::endl;
      std::cout << "4.2f,  -nan : " << std::copysign(4.2f, -nan) << std::endl;
    }

### 出力

    1.0f,  2.0f : 1
    0.0f, -2.0f : -0
    1.5f, -0.0f : -1.5
    -inf,  3.0f : inf
    3.0f,  -inf : -3
     nan, -4.2f : -nan
    4.2f,  -nan : -4.2

### 備考

特定の環境では、早期に `constexpr` 対応されている場合がある：

- GCC 4.6.1 以上

## 実装例

    namespace std {
      float copysign(float x, float y)
      {
        float absolute_value = std::isnan(x) ?
                               std::numeric_limits<float>::quiet_NaN() :
                               std::abs(x);
        return y >= 0 ? absolute_value : -absolute_value;
      }

      double copysign(double x, double y)
      {
        double absolute_value = std::isnan(x) ?
                                std::numeric_limits<double>::quiet_NaN() :
                                std::abs(x);
        return y >= 0 ? absolute_value : -absolute_value;
      }

      long double copysign(long double x, long double y)
      {
        long double absolute_value = std::isnan(x) ?
                                     std::numeric_limits<long double>::quiet_NaN() :
                                     std::abs(x);
        return y >= 0 ? absolute_value : -absolute_value;
      }
    }

## バージョン

### 言語

- C++11

### 処理系

- Clang: 3.0 ✅
- GCC: 4.3 ✅
- ICC: ??
- Visual C++: ??

## 参照

- P0533R9 constexpr for `<cmath>` and `<cstdlib>`
  - C++23での、一部関数の`constexpr`対応
- P1467R9 Extended floating-point types and standard names
  - C++23で導入された拡張浮動小数点数型への対応として、`float`、`double`、`long double`のオーバーロードを`floating-point-type`のオーバーロードに統合し、拡張浮動小数点数型も扱えるようにした