距離の近似値計算
大昔、平方根(sqrt)を使わない距離の近似式が話題になってて、PHP で実験してたのを突然思い出した。忘れないうちにメモしとく。
要するに曲線でなく面を折り畳んで似た形にして、その面を表す式で近似する。
MAX の式で凸面、MIN の式で凹面が出来て、それらを適当な割合で足すとかなり良い感じの形になり、あと x と y の差があり過ぎる時に大きくズレルので減算の補正をかけてる。
乗算無しバージョンの式もあるけど、乗算を使う方ので実験。
3次元版
function approx_distance_3d( $dx, $dy, $dz) { return approx_distance(approx_distance( $dx, $dy ), $dz); }
等とすれば3次元に拡張出来るはず。
試した感じかなり良い値を出す。(ad が近似値で、cd が正確な値)
yoya@sakura:~$ php approx_distance.php 10 10 10 dx:10.000, dy:10.000, dz:10.000, ad:18.000, cd:17.321 yoya@sakura:~$ php approx_distance.php 10 20 30 dx:10.000, dy:20.000, dz:30.000, ad:38.000, cd:37.417 yoya@sakura:~$ php approx_distance.php 10 100 1000 dx:10.000, dy:100.000, dz:1000.000, ad:987.000, cd:1005.037
approx_distance.php
<?php // http://www.flipcode.com/archives/Fast_Approximate_Distance_Functions.shtml function approx_distance( $dx, $dy ) { if ( $dx < 0 ) $dx = -$dx; if ( $dy < 0 ) $dy = -$dy; if ( $dx < $dy ) { $min = $dx; $max = $dy; } else { $min = $dy; $max = $dx; } $approx = ( $max * 1007 ) + ( $min * 441 ); if ( $max < ( $min << 4 )) { $approx -= ( $max * 40 ); } // add 512 for proper rounding return (( $approx + 512 ) >> 10 ); } function approx_distance_3d( $dx, $dy, $dz) { return approx_distance(approx_distance( $dx, $dy ), $dz); } if ($argc !== 4) { echo "Usage: php approx_distance.php 10 20 30\n"; exit(1); } list($prog, $dx, $dy, $dz) = $argv; $ad = approx_distance_3d($dx, $dy, $dz); // aproximate value $cd = sqrt($dx*$dx + $dy*$dy + $dz * $dz); // correct value printf("dx:%.3f, dy:%.3f, dz:%.3f, ad:%.3f, cd:%.3f\n", $dx, $dy, $dz, $ad, $cd);