天天看點

給定四個坐标點,判斷它們能不能組成一個矩形?

已知四個點的坐标為:[0,0],[0,1],[1,1],[1,0],判斷它們能不能組成一個矩形

分析 : 至少有三個内角都是直角的四邊形是矩形,有一個内角是直角的平行四邊形是矩形,對角線相等的平行四邊形是矩形。矩形是一種特殊的平行四邊形,正方形是特殊的矩形。矩形也叫長方形。

給定四個坐标點,判斷它們能不能組成一個矩形?

如圖所示,如果A、B、C、D四點構成矩形的話,那麼△ABC、△BCD就是直角三角形,AC=BD,AD=BC,隻要求證AB²+AC²=BC²即可。

根據勾股定理,a²+b²=c²

接下來直接上代碼,這裡是在thinkphp裡面測試

public function test(){
        $array = [[0,110],[0,1],[1,1],[1,0]];//4個點的坐标
        $s1 = sqrt(($array[1][0] - $array[0][0]) * ($array[1][0] - $array[0][0]) + ($array[1][1] - $array[0][1]) * ($array[1][1] - $array[0][1]));
        $s2 = sqrt(($array[2][0] - $array[0][0]) * ($array[2][0] - $array[0][0]) + ($array[2][1] - $array[0][1]) * ($array[2][1] - $array[0][1]));
        $s3 = sqrt(($array[3][0] - $array[0][0]) * ($array[3][0] - $array[0][0]) + ($array[3][1] - $array[0][1]) * ($array[3][1] - $array[0][1]));
        $array_s = [$s1, $s2, $s3];//長度
        $max_s = max($array_s);//選取最長的一條
        $key = array_search($max_s ,$array_s);
        array_splice($array_s, $key, 1);//去掉最長的一條
        if (bccomp($max_s * $max_s , $array_s[0] * $array_s[0] + $array_s[1] * $array_s[1]) == 0) {//根據勾股定理公式進行判斷,我們這裡采用高精度函數進行比較
        // if ($max_s * $max_s == $array_s[0] * $array_s[0] + $array_s[1] * $array_s[1]) {//不能直接用==進行比較
            return '可以構成矩形';
        } else {
            return '不能構成矩形';
        }
    }
           
給定四個坐标點,判斷它們能不能組成一個矩形?

把點的坐标換成[0,0],[0,1],[1,1],[1,0],又可以組成矩形了;

給定四個坐标點,判斷它們能不能組成一個矩形?

這裡需要注意的是,開根号計算出來的值,都是浮點型資料,是以不能直接用==進行比較,因為會引起錯誤,我們必須用到php的BC高精度函數來進行比較。還有就是不是所有的數都可以用浮點數精确表示,如3.333 二進制表示1*2^1+1*2^0+0*2^(-1)+1*2^(-2)...。記憶體中存儲的僅是真實值得近似值,有精度誤差的。浮點數精度不同。即使在精度相同的情況下,比較也可能會出問題。因為在運算過程中會将記憶體(或高速緩存)中的值加載到CPU浮點寄存器(80 bit擴充精度)中,然後再進入CPU浮點計算單元進行計算,計算結果寫回浮點寄存器,然後寫回記憶體(或高速緩存)。從記憶體到浮點寄存器,浮點數的精度會擴充,從浮點寄存器到記憶體,浮點數的精度會降低(精度擴充通常沒問題,但如果精度降低了,很可能值會發生變化,出現截斷),而浮點運算的結果由于下面還要使用是以暫時儲存在浮點寄存器中留待下次使用(沒有及時寫回記憶體,這是一種優化政策),進而導緻資料并不是記憶體中和記憶體中的資料比較而是浮點寄存器中的值和記憶體中的值進行比較,而無論記憶體中是float類型還是double類型,其精度和浮點寄存器精度都不相同,進而導緻比較結果是不相等。