https://ezoeryou.github.io/cpp-intro/
を読んでいてなるほど!と思ったことを記録します。あくまで、自分が初めて知ったことを書いていきます。
小数点はsetprecision
標準では5桁しか返さない。
cout << setprecision(20);
とすればよくて、テンプレに埋め込んでおけばよいだろう。
powは小数型を返す
double pow(double x, double y);
とかで、実は、int, longを返すわけでない。なので、
int ans = 0;
...
ans = max(ans, pow(val,2));
->
ans = max(ans, (int)pow(val,2));
とかする。
整数リテラルはシングルクォートで区切れる
int m = 1'000'000'000 + 7; cout<<m<<"\n"; // 1000000007
可読性に3つごとにクォート入れられる。便利そうだが、使うことはなさそう。
キャストはstatic_cast<>
int a = -100; long long b;
b = static_cast<long long>(a);
cout << b << "\n"; // -100
競技プログラミング範囲だと、推定してくれるので使わなそうだけどCだと(int)などで済ませていたので存在を知った。
クラスの変換などでは使える。尚、dynamic_castというのもある。これはクラスチェックをしてくれる。
浮動小数点
// 小数点を書くのが大切
// 1.0f: float, 1.0: double, 1.0L: double long
cout << fixed << setprecision(20);
long double ld = 1.0L/2.0L; cout <<ld<<"\n"; //0.50000000000000000000
long double ld2 = 1/2; cout <<ld2<<"\n"; //★0.00000000000000000000
cout << sizeof(long double) <<"\n";
思わず、1/2と書きそうだが、小数点を書くのがポイント。リテラル書かないとfloatというあたりも注意。
fixedは浮動小数点数を固定小数点表記でcoutするためのもの。競技プログラミングなら長い分には大抵十分そう。
10のn乗はe,E
cout << 2e4 << "\n"; //20000
cout << 1e3 << "\n";//1000
cout << 8e-2 << "\n";//0.08
$a*10^b$ を示す。 Pythonだと、$a^b$がa**bなので、使い勝手が違う。Cではpowを使いましょう。
制約が$2 \cdot 10^5$等の時は2e5
とすればいいので使いやすさはこちらの方が良さそう。
infの定義
cout << fixed << setprecision(20);
cout << std::numeric_limits<long>::min() << endl; // -9223372036854775808
cout << std::numeric_limits<long>::max() << endl; // 9223372036854775808
cout << std::numeric_limits<long>::has_infinity << endl; // 0
cout << std::numeric_limits<long>::infinity() << endl; //0(定義なし)
cout << std::numeric_limits<double>::min() << endl; // 0.00000...
cout << std::numeric_limits<double>::max() << endl; // とても大きな数
cout << std::numeric_limits<double>::has_infinity << endl; // 1
cout << std::numeric_limits<double>::infinity() << endl; // inf
cout << -std::numeric_limits<double>::infinity() << endl; // -inf
競技プログラミングでは、整数はmin, maxをinfとして扱い、浮動小数は必要ならinfinityを使うのが良さそう。
ラムダ式の中で相互にラムダ式を呼びたい
# include <bits/stdc++.h>
using namespace std;
int main(){
// f1は intを返し、intを取る関数、のポインタ
int (*f1)(int);
// f1の型を宣言しているので、f2で先行して呼べる
auto f2 = [&](int x) { return f1(x); };
// ここでf2を宣言する。
f1 = [](int x) { return x + 100; };
cout << f2(1) << "\n"; // 101
// 関数ポインタ的な扱いをするときはキャプチャできないので、以下はコンパイルエラーになる
// もし、f3 = [&](int x){..}ができれば通るが、この使い方は一切キャプチャができない
/*
int (*f3)(int);
int (*f4)(int);
f3 = [](int x) { if(x==0) return 0; cout<<"f3:"<<x<<"\n"; f4(x-1); };
f4 = [](int x) { if(x==0) return 0; cout<<"f4:"<<x<<"\n"; f3(x-1); };
f3(3);
*/
}