线上问题之Java数字范围引发的异常

1 场景复现

线上服务做A/B测试,根据a数据切分流量,
这里直接采用hashCode,取最后两位0-99作为流量通道,
取0-10通道测试功能,在做流量切分时,发现流量并比例并不是1:9,
而是达到了惊人的1:1,于是开始排查a数据的分布是否均匀,发现,是均匀的,然后,对a数据进行独立数统计,
抽取数量较多的a数据进行hashCode测试,发现计算之后出现负数,这些负数都挤在了[0,9]这个通道,
因为流量切分直接使用traffic<=10,所以出现流量比例异常的问题。

2 方案

重新设计逻辑:取结果的绝对值:Math.abs(result)。

3 原理

3.1 数据轮转

数据在取值范围内轮转,当数据值超过取值范围时,
按照约定计算新值,本文以byte为例,探究数据是如何轮转的。
1byte占用的存储空间为8bit,即1byte=8bits,取值范围:[ − 2 7 -2^7 27, 2 7 2^7 27-1],
总共可以存储256个数据,数据轮转示意图如下图所示,
数据轮转计算规则:
(1)绝对值按位取反;
(2)加1;
(3)变更符号。

在这里插入图片描述

3.2 Code

byte测试数据轮转样例如下,
数据转换过程在注释中给出。

package com.monkey.java_study.functiontest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;

import java.io.ByteArrayOutputStream;

/**
 * Byte测试.
 *
 * @author xindaqi
 * @date 2021-12-01 17:48
 */
public class ByteTest {

    private static final Logger logger = LogManager.getLogger(ByteTest.class);

    @Test
    public void byteRange() {
        Byte byteMax = Byte.MAX_VALUE;
        Byte byteMin = Byte.MIN_VALUE;
        logger.info(">>>>>>>>Byte max value:{}, byte min value:{}", byteMax, byteMin);
        // 在取值范围内,不进行操作
        Byte var127 = (byte) 0b0111_1111;
        // 128(1000,0000)->绝对值按位取反(0111,1111)->加1(0111,1111+1)=128->变更符号(-128)
        Byte var128 = (byte) 0b1000_0000;
        logger.info(">>>>>>>>Var127:{}, Var128:{}", var127, var128);
        // 129(1000_0001)->绝对值按位取反(0111,1110)->加1(0111,1110+1)=127->变更符号(-127)
        Byte var129 = (byte) 0b1000_0001;
        // -129(-1000,0001):绝对值按位取反(0111,1110)->加1(0111,1111+1)=127->变更符号(127)
        Byte varNegative129 = (byte) -0b1000_0001;
        logger.info(">>>>>>>>Var129:{}, VarNegative129:{}", var129, varNegative129);
    }
}

测试结果如下图所示,与计算逻辑一致。
在这里插入图片描述

4 小结

  • 数据取值在对应的范围内,直接使用,超出范围,重新进行计算,并使用在数据范围内轮转;
  • 数据轮转规则:
    • 绝对值按位取反;
    • 加1;
    • 变更符号。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值