求两条直线的交点坐标

看UdaCity机器学习大纲,发现入门班中有一条:编写算法计算一组直线或平面的交点。

遂从最简单的直角坐标系两条直线的交点开始,

直线1的方程解析式: 2x-y=0;

直线2的方程解析式: 4x-5y=9;

记录下思考过程

版本一

<?php
//求直角坐标系中直线2x-y=0 和 4x-5y=9的交点坐标

$x = 0;
$solution = array();

while(true){
	// 2*$x-$y==0; //这样写不能被程序正确理解
	$y = 2*$x; //将2x-y=0转化成这样进行赋值操作
	//if(2*$x-$y==0 && 4*$x-5*$y==9){ 这样写不能被程序正确理解
	if(4*$x-5*$y==9){ //如果此时的x,y坐标也满足第二个解析式则为解
		$solution[] = array('x'=>$x,'y'=>$y); //将坐标计入解集合中
		break;//由于两条相交的直线最多只有一个交点,只有一个解,找到这个解后直接跳出循环
	}
	//如果不满足第二个解析式则x变量自减0.1继续下一轮循环
	$x -= 0.1;
}

var_dump($solution);

结果

/opt/wwwroot/test/test9.php:19:
array (size=1)
  0 => 
    array (size=2)
      'x' => float -1.5
      'y' => float -3

问题

1, 可以看到当x=0不符合要求后,x一直在进行自减,并恰好找到解,这是人为干预的巧合.因为仅凭x=0不是解并不能判断x是正数还是负数,也就不能判断x应该进行自减还是自增操作.如果x进行了x+=0.1的自增操作(实际上一般都是自增),则该循环将一直找不到正解,陷入无限循环.

2, x变量自增减幅度问题.这里得到的解x=-1.5刚好是自变值0.1的整数倍,从而符合条件被找到.如果正解为-1.51,则不会被0.1的自变量命中,它从-1.5和-1.6之间漏过去了,从而也一直找不到这个正解,陷入无限循环.打个比方一批黄金被埋在0-1000米的直路上的某点,某人从0米开始每隔1米挖一个坑,假设黄金被埋在15.1米的地方,而他挖的坑在第15和第16米的地方,则他找不到黄金,即使他每隔0.5米挖一个坑也找不到,除非每隔0.1米挖一个坑,于是他会错过埋在15.01米处的珍珠.这是采样间隔和采样数量的问题.

版本二

为了避免上面的第一个问题,T提出先对x使用一个大小值区间,观察此时的y是如何变化的,再决定对x进行自增还是自减操作

//求直角坐标系中直线2x-y=0 和 4x-5y=9的交点坐标

//起始小值
$xMin = -10000;
//起始大值
$xMax = 10000;
//大小值区间
$xZone = $xMax-$xMin;
//解集合
$solution = array();

function line1($x){
	$y = 2*$x;
	return $y;
}

function line2($x){
	5*$y = 4*$x-9;
	return $y;
}

//返回同一个x值时的y差值(y2-y1)
function dY($x){
	$y1 = line1($x);
	$y2 = line2($x);
	return $dY = $y2-$y1;
}

function getFixPoint($xMin, $xMax){
	$dYMin = dY($xMin);
	$dYMax = dY($xMax);
	//判断体系
	//如果两个x最值的y差值相乘为负,则说明y差值一正一负,两线相交于最值区间内,最小值自增,最大值自减,互相逼近
	if($dYMin*$dYMax<0){
		$xMin *= 0.5;
		$xMax *= 0.5;
		getFixPoint($xMin, $xMax); //递归调用本方法
	}elseif($dYMin*$dYMax>0){
		//如果两个x最值的y差值相乘为正,则说明y差值同号,x的最值区间处于交点的同一侧,需要移动最值区间
		if($dYMIn+$dYMax>0){
			//如果两个x最值的y差值相加为正,则说明y2>y1,y2在此区间中处于y1上方
			//如果y2的斜率大于y1,则交点在区间左边,最值区间往左移,再递归调用本方法

			//如果y2的斜率小于y1,则交点在区间右边,最值区间往右移,再递归调用本方法
		}elseif($dYMIn+$dYMax<0){
			//如果两个x最值的y差值相加为负,则说明y2<y1,y2在此区间中处于y1下方
			//如果y2的斜率大于y1,则交点在区间右边,最值区间往右移,再递归调用本方法

			//如果y2的斜率小于y1,则交点在区间左边,最值区间往左移,再递归调用本方法
		}
	}else{
		//如果两个y差值相乘为0,则说明两点相交
	}
}

思路

1, 使用区间的方式来判断交点的位置,避免了很多运算,节约了资源.(参考0-1000猜数字的游戏)

2, 斜率之于直线/一次方程/线性,相当于导数之于曲线/二次方程/非线性,在最值区间互相逼近的过程使用了极限的概念,中值定理(?),为接下来的二次/三次/高次方程的求解提供了思路.

缺点:逻辑判断稍微复杂.

版本三

//求直角坐标系中直线2x-y=0 和 4x-5y=9的交点坐标
function getFixPoint($a1,$b1,$c1,$a2,$b2,$c2){
	$x=($b2*$c1 - $b1*$c2)/(-1*$a2*$b1 + $a1*$b2);
	$y=($a2*$c1 - $a1*$c2)/($a2*$b1 - $a1*$b2);
	echo 'x='.$x.'</br>';
	echo 'y='.$y.'</br>';
}

getFixPoint(2,-1,0,4,-5,9);

直接使用高斯消元法,so easy!

x=-1.5
y=-3

思考:

1, 使用算法求数学解时,有公式直接套用公式,站在巨人的肩膀上,比自己造轮子要省时省力高效得多;

2, 算法,机器学习,人工智能这些深入进去之后,还是要用微积分,概率论,线性代数,统计学这些基石.

转载于:https://my.oschina.net/u/3412738/blog/1549298

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值