浮点数表示 & 缓存 & 布隆过滤器

浮点数表示 & 缓存 & 布隆过滤器

  • 1.计算机是如何表示小数
  • 2.缓存
  • 3.布隆过滤器

1.浮点数的表示

引子: 我们先看一个错误示例

public static void main(String[] args) {
		System.out.println(1f == 0.999999f);          // false
    System.out.println(1f == 0.9999999f);         // false
    System.out.println(1f == 0.99999999f);        // true
    System.out.println(1f == 0.999999999999f);    // true
}

注意: 不能使用 "==" 对浮点值进行判断

浮点数之间的等值判断,基本数据类型不能使用 "==" ,包装数据类型不能使用 equals来判断  --- 阿里巴巴Java开发手册[强制]

为什么浮点数不能使用 "==" 判断 ?

计算机是如何表示小数的?

十进制小数

\[D = \sum^{m}_{i=-n} d_{i} * 10^{i} \]

二进制小数

\[B = \sum_{i= -n}^{m} b_{i}*2^{i} \]

IEEE-745浮点标准

\[V = (-1)^s * M *2^E \]

  • s 符号位
  • M 阶码部分
  • E 尾数部分

符号s: 0正,1负

阶码E: float 8bit(-128,127) double 11bit(-1023,1024)

尾数M:float 23bit double 52bit

\[V = x * 2^y \]

根据exp的值,被编码的值可以分为三种

  • 规格化的值
  • 非规格化的值
  • 特殊值

1.规格化的值

\[E = e - Bias \]

\[M = 1+ f \]

  • e - exp表达式的值
  • Bias

\[Bias = 2^{k-1} -1 ; (127,1023) \]

  • M - 调整阶码的值

\[1101.111 = 1.101111 * 2^{3} \]

案例example

\[13.875_{10} = 1101.111_{2} = 1.101111_{2} * 2^{3} \]

\[M = 1 +f \]

\[f = 1011111 \]

\[e = E + Bias = 3 + 127 = 130_{10} = 10000010_{2} \]

13.875
Sign Exponent Mantissa
0x415E0000 = 01000001 01011110 00000000 00000000 0 10000010 10111100000000000000000

浮点数在线转换

2.非规格化的值

\[E = 1- Bias \]

\[M = f \]

3.特殊值

a.当exp全部为1,小数域全为0,表示无穷

b.当exp全部为1,小数域frac不等于0,表示NaN(not a number)

2.缓存

应用缓存 ->性能优化案例:

  • 操作系统
  • 数据库
  • 分布式缓存
  • 本地缓存

缓存目的: 弥补cpu高算力和IO读写慢之间的鸿沟

缓存

缓存问题

3.布隆过滤器

如何判断一个元素是否已经存在?

1.set集合

2.数据+hash , index = hash(xx) % table.length

3.Bloom Filter

布隆过滤器:

  • 减少hash冲突,优化hash函数(多个hash实现)

  • 增加数组长度

    假设用100w的数据量

    • 使用int数组

    \[1*10^{6} * 4 (Byte) = 4*10^{6}/1024 = 4000k \]

    • 使用位数组

    \[1*10^{6} / 8 = 125000(byte) = 127k \]

布隆过滤器的判断方法

  • 布隆过滤器判定某个元素存在,其实有可能存在(hash冲突)
  • 布隆过滤器判定某个元素不存在,则一定不存在

布隆过滤器的使用场景

  • 判断数据在海量数据中是否存在,防止缓存穿透
  • 判定某个URL是否已经处理过

布隆过滤器的实现

package src.bloomFilter;
import java.util.BitSet;

/**
 * @Author deng shuo
 * @Date 6/12/21 10:07
 * @Version 1.0
 */
public class MyBloomFilter {
    
    private static final int DEFAULT_SIZE = 2 << 24;
    
    private static int[] SEEDS = new int[]{3,13,46};
    
    private static BitSet bits = new BitSet(DEFAULT_SIZE);
    
    private SimpleHash[] func = new SimpleHash[SEEDS.length];
    
    public MyBloomFilter(){
        for(int i = 0;i< SEEDS.length;i++){
            func[i] = new SimpleHash(DEFAULT_SIZE,SEEDS[i]);
        }
    }
    
    public void add(Object value){
        for(SimpleHash f: func){
            bits.set(f.hash(value),true);
        }
    }
    
    public boolean contains(Object value){
        boolean res = true;
        for(SimpleHash f:func){
            res = bits.get(f.hash(value));
            if(!res){
                return false;
            }
        }
        return true;
    }
    
    public static class SimpleHash{
        private int cap;
        private int seed;
        
        public SimpleHash(int cap ,int seed){
            this.cap = cap;
            this.seed = seed;
        }
        public int hash(Object value){
            int h;
            return (value == null) ? 0:
                    Math.abs(seed*(cap -1) & (h=value.hashCode())^(h>>>16));
        }
    }
    
}

Guava工具库实现布隆过滤器

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.0.1-jre</version>
</dependency>
// 创建布隆过滤器对象,最多元素数量为10000,期望误报概率为0.01
BloomFilter<Integer> filter = BloomFilter.create(
        Funnels.integerFunnel(), 10000, 0.01);
posted @ 2021-06-12 10:32  dengshuo7412  阅读(84)  评论(0编辑  收藏  举报