[C++]直接访问float变量内存的类,addEpison和subEpison、almostEqual约等于,及浮点数排序函数。从此忘记0.000001 再也不要使用FLT_EPSILON!

本文主要是介绍[C++]直接访问float变量内存的类,addEpison和subEpison、almostEqual约等于,及浮点数排序函数。从此忘记0.000001 再也不要使用FLT_EPSILON!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

探究浮点数奥秘,这里给出一个直接访问float变量内存的类,二进制兼容float,
并给出addEpison和subEpison两个函数
而这两个函数,是模糊比较所需要的方法的基础。

//负数时随着内存值int变大,浮点值绝对值越大
// 80000000   →→→ bf800000  →  ff7fffff  ff800000  ff800001 ffffffff
//    -0       渐变     -1    渐变   -MAX    -INF       -Nan      -Nan
// 
// 正数时随着内存值int变大,浮点值绝对值越大
// 00000000   →→→ 3f800000  →  ff7fffff  7f7fffff  7f800001 7fffffff
//    +0       渐变     +1    渐变   +MAX    +INF       +Nan      +Nan//从负到正遍历浮点数的方法:  ff800000 -> 80000000, 00000000 -> 7f7fffff
//                              -INF         -0        +0         +INFstruct Float
{union{struct{unsigned int Mantissa : 23;unsigned int Exponent : 8;unsigned int Sign : 1;};struct {unsigned int withoutSign : 31;unsigned int : 1;};int _memoryInt = 0;float _float;};operator float&() { return _float; }operator const float&() const { return _float; }operator float() const { return _float; }Float() = default;Float(float f) : _memoryInt((int&)f){}bool equalZero() { return withoutSign == 0; }bool isNan() { return Exponent == 0xFF && Mantissa != 0; }//是正无穷大bool isINF_P() { return _memoryInt == 0x7F800000; }//是负无穷大bool isINF_N() { return _memoryInt == 0xFF800000; }//是无穷大bool isINF_PN() { return (_memoryInt & 0x7F800000) == 0x7F800000; }//非数值void makeNan() { _memoryInt = 0x7FFFFFFF; } //正Nan中内存值最大的//正无穷大void makeINF_P() { _memoryInt = 0x7F800000; }//负无穷大void makeINF_N() { _memoryInt = 0xFF800000; }void makeMax()      { _memoryInt = 0x7F7FFFFF; }void makeMax_N()    { _memoryInt = 0xFF7FFFFF; }void makeMin()      { _memoryInt = 0x00800000; }    //最小值1.1754943510e-38(0x00800000), 次小值1.175494491e-38(0x00800001)void makeMin_N()    { _memoryInt = 0x80800000; }void makeTrueMin() { _memoryInt = 0x00000001; }     //最小值1.4012984643e-45F(0x00000001),次小值2.803e-45  2.8025969286496341e-45 (0x00800002)void makeTrueMin_N() { _memoryInt = 0x80000001; }//增加一个极小值,使得比当前值大;+max,+/-INF,+/-Nan不受影响void addEpison(){if ((unsigned int)_memoryInt >= 0xFF800000u) return; //负无穷大,负Nanif (_memoryInt >= 0x7F7FFFFF) return; //正最大值,正无穷大,正Nanif (_memoryInt == 0x80000000)   //负0_memoryInt = 0x00000001;    //TrueMinelse{_memoryInt += 1 - ((_memoryInt<0)<<1);}}//减少一个极小值,是的比当前值小void subEpison() {if ((unsigned int)_memoryInt >= 0xFF800000u) return; //负最大值,负无穷大,负Nanif (_memoryInt >= 0x7F800000) return; //正无穷大,正Nanif (_memoryInt == 0x00000000)   //正0_memoryInt = 0x80000001;    //TrueNegMinelse{_memoryInt -= 1 - ((_memoryInt < 0) << 1);}}bool almostEqual(const Float& other, unsigned int episonCount) const{if (((unsigned int)_memoryInt >= 0xFF800000u) || (_memoryInt >= 0x7F800000)|| ((unsigned int)other._memoryInt >= 0xFF800000u) || (other._memoryInt >= 0x7F800000))return _float == other._float; //无穷大,Nanint absA = _memoryInt < 0 ? 0x80000000 - _memoryInt : _memoryInt;int absB = other._memoryInt < 0 ? 0x80000000 - other._memoryInt : other._memoryInt;return (episonCount + unsigned int(absA - absB)) <= (episonCount << 1);}
};
    Float a = 1.f / 3;Float b = 0.5f - 1.f / 6;a += a;b += b;{bool test = a == b;puts(test ? "true" : "false");  //false}{bool test = a.almostEqual(b, 1); //一个精度差距?puts(test ? "true" : "false");  //true}{Float A = a;A.addEpison(); //手动增加一个精度差距bool test = A.almostEqual(b, 1); //一个精度差距?puts(test ? "true" : "false");  //false}{Float A = a;A.addEpison(); //手动增加一个精度差距bool test = A.almostEqual(b, 2); //二个精度差距?puts(test ? "true" : "false");  //true}{Float x1 = a, x2 = a;x1.addEpison();x2.subEpison();bool test2 = a == b || x1 == b || x2 == b;puts(test2 ? "true" : "false"); //true}

下面给出一个浮点数排序函数,使用他能正确使包含无穷大、Nan的浮点数组成功排序

[](float a, float b) {bool isnanA = isnan(a), isnanB = isnan(b);if (isnanA || isnanB){if (!isnanB){return ((int&)a & 0x80000000) != 0;}if (!isnanA){return ((int&)b & 0x80000000) == 0; }if (((int&)a < 0) != ((int&)b < 0))return (int&)a < (int&)b;else //两nan符号相同return (((int&)a & 0x7FFFFF) < ((int&)b & 0x7FFFFF)) != ((int&)a < 0);}if ((int&)a == (int&)b)return false;else if (a < b)return true;else if (b < a)return false;elsereturn (int&)a < (int&)b;}

这篇关于[C++]直接访问float变量内存的类,addEpison和subEpison、almostEqual约等于,及浮点数排序函数。从此忘记0.000001 再也不要使用FLT_EPSILON!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/747505

相关文章

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Mybatis 传参与排序模糊查询功能实现

《Mybatis传参与排序模糊查询功能实现》:本文主要介绍Mybatis传参与排序模糊查询功能实现,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、#{ }和${ }传参的区别二、排序三、like查询四、数据库连接池五、mysql 开发企业规范一、#{ }和${ }传参的

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

C++变换迭代器使用方法小结

《C++变换迭代器使用方法小结》本文主要介绍了C++变换迭代器使用方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、源码2、代码解析代码解析:transform_iterator1. transform_iterat

详解C++中类的大小决定因数

《详解C++中类的大小决定因数》类的大小受多个因素影响,主要包括成员变量、对齐方式、继承关系、虚函数表等,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 非静态数据成员示例:2. 数据对齐(Padding)示例:3. 虚函数(vtable 指针)示例:4. 继承普通继承虚继承5.

C++中std::distance使用方法示例

《C++中std::distance使用方法示例》std::distance是C++标准库中的一个函数,用于计算两个迭代器之间的距离,本文主要介绍了C++中std::distance使用方法示例,具... 目录语法使用方式解释示例输出:其他说明:总结std::distance&n编程bsp;是 C++ 标准

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa