26 Mart 2020 Perşembe

std::abs metodu

Giriş
C++17'den önce std::abs() tam bir keşmekeş. Aynı metod <cstdlib> ve <cmath> içinde tanımlıydı.
<cstdlib> parametre olarak integral tipler alıyordu, <cmath> ise parametre olarak floating tipleri alıyordu.

Sanırım cmath içindeki metodları tercih etmek daha iyi.
1. cmath Kütüphanesi
Metodların imzası şöyleydi.
float abs(float);
double abs(double);
long double abs(long double);
Örnek
cmath içindeki metodu override etmek mümkün. Ancak bu aslında bence bir hata. Şöyle yaparız.
#include <iostream>
#include <cmath>

/* intentionally incorrect abs() which seems to override std::abs() */
int abs(int a){return a > 0? -a : a ;}

int main(){
  int a = abs(-5);
  int b = std::abs(-5);
  std::cout<< a << std::endl<< b <<std::endl;
  return 0;
}
Örnek
double ile 18 hane precision'a sahip sayılarla çalışılamayacağı için hatalar olabilir. Elimizde şöyle bir kod olsun.
#include <iostream>
#include <cmath>

using namespace std;

int main()
{
  long long int a, b;
  long long int c;

  cin >> a >> b; //1000000000000000000 ve 2 girelim

  c = abs(a) + abs(b);
  cout << c;
  cout << endl;
}
Çıktı olarak 1000000000000000002 yerine 1000000000000000000 sayısını alırız. Çünkü double 18 hane precision'a çıkınca hatalı çalışır.

2. cstdlib Kütüphanesi
Şu satır dahil edilir.
#include <cstdlib>
Metodların imzası şöyleydi. cmath'teki metodlardan farklı olarak parametreler primitive tip.
int abs(int);
long abs(long);
long long abs(long long);
Bu metodlar yerine 32 bit tam sayılarda şu yöntem de kullanılabilir. Ancak bu yöntem portable değil.
y = x >> 31
(x + y) ^ y // This gives abs(x)
Niçin std::abs
Bir sayının mutlak değerini almak sayı eksi ise onu artık yapmak anlamına gelir. Yani aslında şöyle yapabiliriz.
int absoluteValue = value < 0 ? -value : value;
Ancak -0.0 gibi değerlere dikkat etmek gerekiyor. Aradaki fark şöyle. Bu örnekte yukarıdaki kodun yaptığı <0 kontrolü işe yaramıyor. Dolayısıyla -0 için kendi abs metodumuz yine -0 veriyor.
double d = -.0;
double a = d < 0 ? -d : d;
std::cout << d << ' ' << a << ' ' << std::abs(d);
Çıktı olarak şunu alırız.
-0 -0 0
Diğer 
Ayrıca std::labs(), std::llabs(), std::imaxabs() metodları da var.

std::labs
Metodların imzası şöyle
long labs( long n );

long long labs( long long n );
cstdlib içindeki std::abs() ile aynı işi yapıyor aslında. Var olmasının sebebinin açıklaması şöyle
You don't really need it in C++ code, because we had a long overload of std::abs since about forever. But if you have some C code (that by sheer coincidence also compiles with a C++ compiler), and it uses labs, you can build it with a C++11 compiler and standard library.
imaxabs metodu
imaxabs ile en küçük değerin mutlak değerini almak tanımsızdır.
intmax_t i = INTMAX_MIN;intmax_t j = imaxabs(i); //Tanımsız


Hiç yorum yok:

Yorum Gönder