首页 > 其他分享 >浮点数之间的比较,基本运算这些究竟是怎么实现的

浮点数之间的比较,基本运算这些究竟是怎么实现的

时间:2024-08-29 12:06:23浏览次数:4  
标签:uiA uiB 运算 union 浮点数 f32 float32 究竟

科学计算当中会用到不少浮点数的操作,这些浮点数可能是16位,32位,64位,80位甚至是128位。开源项目SoftFloat提供了一个高效的浮点运算实现,可以在没有硬件支持的情况下,高效模拟浮点数的各种操作。

那么,浮点数之间的比较,基本运算这些究竟是怎么实现的呢,可以拿32位浮点数作为例子。

这是32位浮点数加法的实现,首先声明了一个结构体float32_t。

typedef struct { uint32_t v; } float32_t;

这提供了32位浮点数的底层位表示,同时还声明了一个union。

union ui32_f32 { uint32_t ui; float32_t f; };

一方面保存了浮点数的位表示,另一方面也可以转换为32位无符号整型直接进行比较,这在后面的算法当中会直接涉及。先看看加法。

float32_t f32_add( float32_t a, float32_t b )
{
    union ui32_f32 uA;
    uint_fast32_t uiA;
    union ui32_f32 uB;
    uint_fast32_t uiB;
#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
    float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t );
#endif

    uA.f = a;
    uiA = uA.ui;
    uB.f = b;
    uiB = uB.ui;
#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
    if ( signF32UI( uiA ^ uiB ) ) {
        return softfloat_subMagsF32( uiA, uiB );
    } else {
        return softfloat_addMagsF32( uiA, uiB );
    }
#else
    magsFuncPtr =
        signF32UI( uiA ^ uiB ) ? softfloat_subMagsF32 : softfloat_addMagsF32;
    return (*magsFuncPtr)( uiA, uiB );
#endif

}

这里uiA和uiB是存储无符号整型的,signF32UI是提取符号位的。signF32UI(uiA ^ uiB)判断符号位是否相同,如果相同则调用加法,如果符号位不相同则调用减法,因为没有浮点数,所以只能通过整型去模拟,另外,union存储浮点和整型有一个名词,似乎叫类型双关技术?不过这里union存储的只是位表示,并不是真的浮点数。

float32_t f32_sub( float32_t a, float32_t b )
{
    union ui32_f32 uA;
    uint_fast32_t uiA;
    union ui32_f32 uB;
    uint_fast32_t uiB;
#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
    float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t );
#endif

    uA.f = a;
    uiA = uA.ui;
    uB.f = b;
    uiB = uB.ui;
#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
    if ( signF32UI( uiA ^ uiB ) ) {
        return softfloat_addMagsF32( uiA, uiB );
    } else {
        return softfloat_subMagsF32( uiA, uiB );
    }
#else
    magsFuncPtr =
        signF32UI( uiA ^ uiB ) ? softfloat_addMagsF32 : softfloat_subMagsF32;
    return (*magsFuncPtr)( uiA, uiB );
#endif

}

减法则是在判断符号那里反过来,其它一样。这时候可以看看比较运算怎么做。

bool f32_le( float32_t a, float32_t b )
{
    union ui32_f32 uA;
    uint_fast32_t uiA;
    union ui32_f32 uB;
    uint_fast32_t uiB;
    bool signA, signB;

    uA.f = a;
    uiA = uA.ui;
    uB.f = b;
    uiB = uB.ui;
    if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
        softfloat_raiseFlags( softfloat_flag_invalid );
        return false;
    }
    signA = signF32UI( uiA );
    signB = signF32UI( uiB );
    return
        (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1)
            : (uiA == uiB) || (signA ^ (uiA < uiB));

}

最后的表达式有点绕,一步一步拆分。首先符号不相等(一正一负)的话,如果A的符号是1,也就是负数,肯定比B小,否则走 || 后的分支。把A和B的最高位(符号位)剔除,判断是否相同,也就是+0和-0的情况,这里记得别漏了前面的!符号,因为判断两者是否都为0;如果A和B同号的话,如果都是正数则直接比较,如果都是负数,则前面的signA会对结果取反。

结语

最近处于校招阶段,正在准备,有时间会分享自己的心得和体会,希望尽早上岸。

本博客参考豆荚加速器。转载请注明出处!

标签:uiA,uiB,运算,union,浮点数,f32,float32,究竟
From: https://www.cnblogs.com/veee/p/18386397

相关文章

  • 6 Python运算符和表达式
    本篇是Python系列教程第6篇,更多内容敬请访问我的Python专栏Python运算符和Java类似,但也有个别不同。Python表达式和Java的区别是Python表达式不用跟“;”结尾。1算术运算符算术运算符用于执行基本的数学运算,如加减乘除等。加法(+):将两个数相加。result......
  • C语言--运算符3
    自增自减运算符i++,i--运算符在后,在表达式中先用i的值,下条语句i的值自增或者自减#include<stdio.h>intmain(){inti=1;intnum;num=i++;printf("num=%d,i=%d\n",num,i);//num=1,i=2return0;}++i先加,后用#include<stdio.h>intmain(){inti=1;intnum;......
  • C语言位运算
    在C语言中,位运算是对二进制位进行的操作。以下是关于C语言位运算的介绍:一、常见的位运算符按位与(&):规则:两个对应的二进制位都为1时,结果位为1,否则为0。例如:5(二进制为0101)与3(二进制为0011)进行按位与运算,结果为0001,即1。按位或(|):规则:两个对应的二进制位只要......
  • 【解析几何笔记】9. 向量的内积运算
    9.向量的内积运算定义:有向量α,β\pmb{\alpha},\pmb{\beta}α,......
  • 【C++基础】多种函数重载和运算符重载
    目录一、函数重载1.参数类型不同的重载讲解2.参数个数不同的重载讲解3.参数顺序不同的重载讲解4.默认参数与函数重载讲解二、运算符重载1.运算符重载的基本语法示例讲解函数内部的操作:运算符的使用:2.运算符重载的常见用法2.1重载<<和>>运算符(用于输......
  • 超详细!SQL运算符的操作练习-笔记-04章:运算符
    写在前面的话(•̀.̫•́)✧即将学习数据库系统的课程,此文为预习与自学,自学配套课程链接为:MySQL数据库入门到大牛,mysql安装到优化,百科全书级,全网天花板_哔哩哔哩_bilibili时间不够可以不看,前五章内容都比较简单,纯看笔记也能学会。本文主要内容是学习和练习运算符,这......
  • 浮点数算法的内部实现
     科学计算当中会用到不少浮点数的操作,这些浮点数可能是16位,32位,64位,80位甚至是128位。开源项目SoftFloat提供了一个高效的浮点运算实现,可以在没有硬件支持的情况下,高效模拟浮点数的各种操作。 那么,浮点数之间的比较,基本运算这些究竟是怎么实现的呢,可以拿32位浮点数作为例子。......
  • C语言--运算符2
    目录位运算符1、&按位与2、|按位或3、~按位取反4、^按位异或5、位移(1)右移>>(2)左移<<位运算符例:128十进制转二进制正数在内存中以原码形式存放,负数在内存中以补码形式存放正数的原码=反码=补码原码:将一个整数,转换成二进制,就是其原码。如64的原码为:0100 00......
  • Day09_0.1基础学习MATLAB学习小技巧总结(9)——数组运算
    利用空闲时间把碎片化的MATLAB知识重新系统的学习一遍,为了在这个过程中加深印象,也为了能够有所足迹,我会把自己的学习总结发在专栏中,以便学习交流。素材来源“数学建模清风”特此说明:本博客的内容只在于总结在使用matlab中的一些小技巧,并非教程,若想系统的学习MATLAB,也可以移步......
  • Day07_0.1基础学习MATLAB学习小技巧总结(7)——矩阵算数运算
    利用暑假的时间把碎片化的MATLAB知识重新系统的学习一遍,为了在这个过程中加深印象,也为了能够有所足迹,我会把自己的学习总结发在专栏中,以便学习交流。素材来源“数学建模清风”特此说明:本博客的内容只在于总结在使用matlab中的一些小技巧,并非教程,若想系统的学习MATLAB,也可以移......