foreach next 操作数组指针移动问题,多个数连加,连除,连减,连乘php版本

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);
}

 对象指针操作参看

https://www.cnblogs.com/zx-admin/p/10430782.html

以下是一个实例

 连续 加 减 乘 除

$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/

https://blog.csdn.net/asty9000/article/details/82860124

 

posted on 2018-10-22 19:48  zh7314  阅读(764)  评论(0编辑  收藏  举报