Open yumetodo opened 8 years ago
キャストしているのはオーバーフロー対策ですね。 二乗の計算は意外とあっさりオーバーフローするので、少なくともデフォルト動作ではdoubleへのキャストは妥当だと思います。
@Nagarei
オーバーフロー対策
double
とstd::uint64_t
だと後者のほうが範囲広いんですよね・・・。
いずれにせよ
43ea90edc48ec8d9da8c93c1d95a46014f9cce34
でstatic_cast_if
を使うように書き換えてしまったのでオーバーフローを考えるならまずい
doubleは64bitのとき精度はかなり落ちますが、300桁以上の数値を扱えたはずなので、150桁までの数値なら二乗できるはずです。 とはいえuint64_tでも8.5e+9までの数値なら二乗できるので良いような気もしますが。
精度の問題があるのであまり浮動小数点型にキャストしたくないんですよね・・・。 まあ確かに精度を抜きにすればdoubleは最適解ですが・・・・。
たとえば、std::numeric_limits<std::int32_t>::max() < sqrt(std::numeric_limits<std::int64_t>::max())
の関係が成り立つので、std::int32_t
の入力ならstd::int64_t
を返すほうがいい気がしますしということで
double
にという手もあるかなと思うわけですが、実装が複雑になるか・・・。
なるほど。 仮実装でとりあえずdoubleにした後、上の動作が実装でき次第差し替えるというのはどうでしょう。
了解ですが、テストどうやって書こう・・・
https://github.com/Nagarei/DxLibEx/blob/d8f29942a900d5f8c888dfeb99a6f64babcdd2b4/dxlibex/basic_types/point2d.hpp#L628
二次元ベクトルの外積は、二ベクトルのなす平行四辺形の面積(符号の話はおいておいて)で定義しているが、
これを作成した時の私は https://github.com/Nagarei/DxLibEx/commit/16271b650c77ec6df9ee6109b94121a1a7a6f322
double
型にキャストして計算している。計算式そのものは上図からsin/cosの定義とベクトルの内積と加法定理で証明できるから、
pa.x * pb.y + pa.y * pb.x
であっているけど、キャストはいらない気がしている。(中身掛け算と足し算ですし)ただ、これを作るときに参考にしたOpenCVでは http://docs.opencv.org/master/db/d4e/classcv_1_1Point__.html#a946769d5545dba5d328486602aae2ac3 https://github.com/opencv/opencv/blob/c8693f01a3b557fdf0ccb4fd6bff2fe616e7ce32/modules/core/include/opencv2/core/types.hpp#L1117 doubleにキャストしている。
@Nagarei キャストどうしましょうか