2018年10月20日10:39:40
先说结论,foreach 维护的是一套属于自己的数组指针
会在操作数据的时候,分裂一套变量地址,即使你强制使用 & 取地址一样会分裂,不会引用同一套指针
所有在foreach的时候需要主动操作指针的时候,就会出现问题,很容易key超出变量的长度
测试demo
1,测试指针是否同步,会受到数组操作函数的影响
$a = [3,4,5,6,7];
foreach ($array as $k => $v) {
p($v);
p(next($array));
}
结果是不受影响,如果需要复杂指针操作就需要,自己移动指针,使用以下的方法
while(key($a)!==null){
echo key($a)."=>".current($a)."\n";
next($a);
}
以下是一个实例
连续 加 减 乘 除
$parameter = [10, 20, 30, 40, 50, 60];
$rr = $parameter;
for ($i = 1; $i <= (count($rr) - 1 ); $i++) {
p($i);
reset($parameter);
$data_1 = current($parameter);
array_shift($parameter);
$data_2 = current($parameter);
array_shift($parameter);
// if (!empty($data_2)) {
$res = bcdiv($data_1, $data_2, 2);
array_unshift($parameter, $res);
p($parameter);
}
封装过的方法
2019年1月2日12:07:01 经过修改过的方法
//多个参数 bc系列 加 减 乘 除 可扩展
if (!function_exists('multiple_parameters_bc')) {
/*
* add 加
* sub 减
* mul 乘
* div 除
*/
function multiple_parameters_bc($type = 'add', $accuracy = 2, ...$parameter) {
// pp($parameter);
//bc 对小数点位数不是四舍五入,先高精度计算最后对小数点位数四舍五入
// $calculation_accuracy 计算时保持的小数点精度 返回值保留的精度$accuracy
$calculation_accuracy = 10;
if (count($parameter) < 2) {
throw new \Exception('参数少于2个');
}
//防止数组操作导致循环次数异常
$temp = $parameter;
for ($i = 1; $i <= (count($temp) - 1 ); $i++) {
// p($i);
//保证指针一直指向数组第一个元素
reset($parameter);
//获取第一个元素
$data_1 = current($parameter);
array_shift($parameter);
//获取第二个元素
$data_2 = current($parameter);
array_shift($parameter);
if ($type == 'add') {
$res = bcadd($data_1, $data_2, $calculation_accuracy);
} elseif ($type == 'sub') {
$res = bcsub($data_1, $data_2, $calculation_accuracy);
} elseif ($type == 'mul') {
// if ((int) $data_2 == 0) {
// throw new \Exception('被乘元素不能为0');
// }
$res = bcmul($data_1, $data_2, $calculation_accuracy);
} elseif ($type == 'div') {
if ((int) $data_2 == 0) {
throw new \Exception('被除元素不能为0');
}
$res = bcdiv($data_1, $data_2, $calculation_accuracy);
} else {
throw new \Exception('计算类型不识别');
}
//计算结果再次压入队首,循环继续使用
array_unshift($parameter, $res);
}
//加减不需要四舍五入,只需要截取小数位精度 ,乘除需要四舍五入
if ($type == 'add') {
return number_format($parameter['0'], $accuracy, '.', '');
} elseif ($type == 'sub') {
return number_format($parameter['0'], $accuracy, '.', '');
} elseif ($type == 'mul') {
return round($parameter['0'], $accuracy);
} elseif ($type == 'div') {
return round($parameter['0'], $accuracy);
} else {
throw new \Exception('计算类型不识别');
}
}
}
经过测试没有什么问题,注意出发的时候,结果溢出,因为是没计算完就四舍五入,如果特殊需要,可以自己优化一下除法
修改版本1
function multiple_parameters_bc(string $type = '+', int $accuracy = 2, ...$parameter) {
// pp($parameter);
//bc 对小数点位数不是四舍五入,先高精度计算最后对小数点位数四舍五入
// $calculation_accuracy 计算时保持的小数点精度 返回值保留的精度$accuracy
$calculation_accuracy = 30;
if (count($parameter) < 2) {
throw new \Exception('参数少于2个');
}
//防止数组操作导致循环次数异常
$temp = $parameter;
for ($i = 1; $i <= (count($temp) - 1 ); $i++) {
// p($i);
//保证指针一直指向数组第一个元素
reset($parameter);
//获取第一个元素
$data_1 = current($parameter);
array_shift($parameter);
//获取第二个元素
$data_2 = current($parameter);
array_shift($parameter);
if ($type == '+') {
$res = bcadd($data_1, $data_2, $calculation_accuracy);
} elseif ($type == '-') {
$res = bcsub($data_1, $data_2, $calculation_accuracy);
} elseif ($type == '*') {
// if ((int) $data_2 == 0) {
// throw new \Exception('被乘元素不能为0');
// }
$res = bcmul($data_1, $data_2, $calculation_accuracy);
} elseif ($type == '/') {
if ((int) $data_2 == 0) {
throw new \Exception('被除元素不能为0');
}
$res = bcdiv($data_1, $data_2, $calculation_accuracy);
} else {
throw new \Exception('计算类型不识别');
}
//计算结果再次压入队首,循环继续使用
array_unshift($parameter, $res);
}
//加减不需要四舍五入,只需要截取小数位精度 ,乘除需要四舍五入
if ($type == '+') {
return number_format($parameter['0'], $accuracy, '.', '');
} elseif ($type == '-') {
return number_format($parameter['0'], $accuracy, '.', '');
} elseif ($type == '*') {
return round($parameter['0'], $accuracy);
} elseif ($type == '/') {
return round($parameter['0'], $accuracy);
} else {
throw new \Exception('计算类型不识别');
}
}
参考
http://www.phppan.com/2013/04/foreach-exception/