Skip to main content

php7.1以上浮点数序列号精度问题

问题说明

Php7.1以上版本 在对浮点数序列化时 会导致多出很多位小数,

  • 举例

    $amount = 9.70;
    $data = [];
    $data['value'] = $amount * 100;
    echo json_encode($data);
  • 显示结果:

    {"value":969.9999999999999}

处理办法

普通数字处理

  • 举例

    //通过round函数来处理
    $amount = 9.70;
    $data = [];
    $data['value'] = round($amount * 100, 2);
    echo json_encode($data);
    //通过强制string处理
    $amount = 9.70;
    $data = [];
    $data['value'] = (string)($amount * 100, 2);
    echo json_encode($data);
  • 输出结果:

    {"value":970}

商品价格处理

  • 增加价格有效位处理函数

    /**
    * 修正价格
    * @param float $amount 价格总数
    * @param int $effective_bit 价格保留有效位数
    * @return float|int
    */
    function revisedEffectivePrice(float $amount, int $effective_bit)
    {
    if ($amount == 0) { //如果明确为0 则直接返回0 比如免费点卡
    return $amount;
    }
    //货币的最低有效面额,$effective_bit=2 最低有效面额100,$effective_bit = -2 最低有效面额0.01
    $baseUnitAmount = pow(10, $effective_bit);
    //$effective_bit<0 ? 处理保留几位有效小数位 : 处理保留几位有效整数位
    $amount = $effective_bit < 0 ? round($amount, -$effective_bit) : round($amount / $baseUnitAmount) * $baseUnitAmount;
    //如果有效位处理后价格为0 则返回最低有效面额,确保价格不能为0
    return $amount ? $amount : $baseUnitAmount;
    }
  • 币种类增加币种价格有效位处理函数

    /**
    * 修正价格
    * @param float $amount
    * @param string $currency_code
    * @return float|number
    * @throws Exception
    */
    public static function revisedPrice(float $amount, string $currency_code = CURRENCY){
    return revisedEffectivePrice($amount,self::getEffectiveBit($currency_code));
    }
  • 商品价格调用币种价格有效位处理函数修复价格

    /**
    * 购物车价格有效位修复
    * @throws Exception
    */
    public function revisedPrice(){
    $this->tax_amount_cart = CurrenciesModel::revisedPrice($this->tax_amount_cart,CURRENCY);
    $this->pay_amount_cart = CurrenciesModel::revisedPrice($this->pay_amount_cart,CURRENCY);
    $this->pay_amount_cart_base = CurrenciesModel::revisedPrice($this->pay_amount_cart_base,DEFAULT_CURRENCY);
    $this->pay_amount_cart_no_gst_vc = CurrenciesModel::revisedPrice($this->pay_amount_cart_no_gst_vc,CURRENCY);
    $this->pay_amount_cart_no_gst_vc_base = CurrenciesModel::revisedPrice($this->pay_amount_cart_no_gst_vc_base,DEFAULT_CURRENCY);
    $this->vc_order_total_base = CurrenciesModel::revisedPrice($this->vc_order_total_base,DEFAULT_CURRENCY);
    }