📜  浮点数和双精度值的异常行为

📅  最后修改于: 2022-05-13 01:54:27.461000             🧑  作者: Mango

浮点数和双精度值的异常行为

Float是 32 位 IEEE 754 单精度浮点数 1 位表示符号,(8 位表示指数,23* 表示值),即 float 有 7 位十进制数的精度。

Double是 64 位 IEEE 754 双精度浮点数(符号 1 位,指数 11 位,值 52* 位),即 double 具有 15 位十进制精度。

本文重点讨论浮点和双精度值的异常行为。

方案一:

C
// C program to illustrate the abnormal
// behaviours of floating point value
#include 
  
// Driver Code
int main()
{
    float f = 0.2;
    if (f == 0.2)
        printf("it's geek time");
    else if (f < 0.2)
        printf("it's party time");
    else
        printf("it's movie time");
    return 0;
}


C++
// C++ program to illustrate the abnormal
// behaviours of floating point value
#include 
using namespace std;
  
// Driver Code
int main()
{
    float f = 0.2;
    if (f == 0.2)
        cout << "it's geek time";
    else if (f < 0.2)
        cout << "it's party time";
    else
        cout << "it's movie time";
    return 0;
}


C
// C program to illustrate the above idea
#include 
  
// Driver Code
int main()
{
    // Declare as double or long double
    // or long double f = 0.2;
    double f = 0.2;
    if (f == 0.2)
        printf("it's geek time");
    else if (f < 0.2)
        printf("it's party time");
    else
        printf("it's movie time");
  
    return 0;
}


C++
// C program to illustrate the above idea
#include 
using namespace std;
  
// Driver Code
int main()
{
    // Declare as double or long double
    // or long double f = 0.2;
    double f = 0.2;
    if (f == 0.2)
        cout << "it's geek time";
    else if (f < 0.2)
        cout << "it's party time";
    else
        cout << "it's movie time";
    return 0;
}


C
// C program to illustrate the above idea
#include 
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Typecast 0.2 as a float
    if (f == (float)0.2)
        printf("it's geek time");
    else if (f < (float)0.2)
        printf("it's party time");
    else
        printf("it's movie time");
    return 0;
}


C++
// C++ program to illustrate the above idea
#include 
using namespace std;
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Typecast 0.2 as a float
    if (f == (float)0.2)
        cout << "it's geek time";
    else if (f < 0.2)
        cout << "it's party time";
    else
        cout << "it's movie time";
    return 0;
}


C
// C program to illustrate the above idea
#include 
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Replace 0.2 with 0.2f
    if (f == 0.2f)
        printf("it's geek time");
    else if (f < 0.2f)
        printf("it's party time");
    else
        printf("it's movie time");
    return 0;
}


C++
// C++ program to illustrate the above idea
#include 
using namespace std;
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Replace 0.2 with 0.2f
    if (f == 0.2f)
        cout << "it's geek time";
    else if (f < 0.2)
        cout << "it's party time";
    else
        cout << "it's movie time";
    return 0;
}


C
// C program to illustrate the above idea
#include 
#include 
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Declare a variable with very small value
    // float acceptableDifference = 1e-9;
    float acceptableDifference = 0.00000001;
  
    // Check if the diff of both values is
    // less than this variable
    if (abs(f - 0.2) < acceptableDifference)
        printf("it's geek time");
    else if (f < 0.2)
        printf("it's party time");
    else
        printf("it's movie time");
  
    return 0;
}


C++
// C++ program to illustrate the above idea
#include 
using namespace std;
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Declare a variable with very small value
    // float acceptableDifference = 1e-9;
    float acceptableDifference = 0.00000001;
  
    // Check if the diff of both values is
    // less than this variable
    if (abs(f - 0.2) < acceptableDifference)
        cout << "it's geek time";
    else if (f < 0.2)
        cout << "it's party time";
    else
        cout << "it's movie time";
    return 0;
}


输出:

it's movie time

说明:在上面的程序中,输出是“现在是电影时间”而不是“这是极客时间”。所以这里是解释,因为 f 是一个浮点值,'0.2' 是一个双精度值,所以由于两种数据类型的精度差异,可以看到这种异常行为。在语句中,如果(f==0.2), f 正在与 0.2 进行比较,因此在内部它是这样写的:

if((double)(float)(0.2) == (0.2))

由于 0.2 是在上述行中声明和分配时第一次转换为浮点数(因此精度降低并且在发生某些值和某些信息/精度丢失后四舍五入),然后再次转换为双精度在 if 语句中,但无法取回丢失的值。因此,可以看到这种行为。

为了更清楚地理解,让我们以基数为 10 的数字系统为例(类比)。

让我们取 10/3 并将其表示为 5 个有效数字:3.3333 或 3.3334(在四舍五入的情况下)。那就是“浮动”f。现在将f的值转换为具有 8 位有效数字的值(f 为“double”)- 3.3333000 或 3.3334000(在四舍五入的情况下)。那不等于 3.3333333(10/3 的值直接作为双精度数)。

避免异常行为的方法

在声明/初始化变量时,用 double f = 0.2 或 long double f = 0.2 替换 float f = 0.2:

下面是用于说明上述想法的 C/C++ 程序:

C

// C program to illustrate the above idea
#include 
  
// Driver Code
int main()
{
    // Declare as double or long double
    // or long double f = 0.2;
    double f = 0.2;
    if (f == 0.2)
        printf("it's geek time");
    else if (f < 0.2)
        printf("it's party time");
    else
        printf("it's movie time");
  
    return 0;
}

C++

// C program to illustrate the above idea
#include 
using namespace std;
  
// Driver Code
int main()
{
    // Declare as double or long double
    // or long double f = 0.2;
    double f = 0.2;
    if (f == 0.2)
        cout << "it's geek time";
    else if (f < 0.2)
        cout << "it's party time";
    else
        cout << "it's movie time";
    return 0;
}
输出:
it's geek time

0.2强制转换为float,而if语句里面比较



下面是用于说明上述想法的 C/C++ 程序:

C

// C program to illustrate the above idea
#include 
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Typecast 0.2 as a float
    if (f == (float)0.2)
        printf("it's geek time");
    else if (f < (float)0.2)
        printf("it's party time");
    else
        printf("it's movie time");
    return 0;
}

C++

// C++ program to illustrate the above idea
#include 
using namespace std;
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Typecast 0.2 as a float
    if (f == (float)0.2)
        cout << "it's geek time";
    else if (f < 0.2)
        cout << "it's party time";
    else
        cout << "it's movie time";
    return 0;
}
输出:
it's geek time

将 0.2 写为浮点值:

 下面是用于说明上述想法的 C/C++ 程序:

C

// C program to illustrate the above idea
#include 
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Replace 0.2 with 0.2f
    if (f == 0.2f)
        printf("it's geek time");
    else if (f < 0.2f)
        printf("it's party time");
    else
        printf("it's movie time");
    return 0;
}

C++

// C++ program to illustrate the above idea
#include 
using namespace std;
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Replace 0.2 with 0.2f
    if (f == 0.2f)
        cout << "it's geek time";
    else if (f < 0.2)
        cout << "it's party time";
    else
        cout << "it's movie time";
    return 0;
}
输出:
it's geek time

通过声明一个acceptableDifference变量来检查两个值之间的差异是否非常小(1e-9):

下面是用于说明上述想法的 C/C++ 程序:

C

// C program to illustrate the above idea
#include 
#include 
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Declare a variable with very small value
    // float acceptableDifference = 1e-9;
    float acceptableDifference = 0.00000001;
  
    // Check if the diff of both values is
    // less than this variable
    if (abs(f - 0.2) < acceptableDifference)
        printf("it's geek time");
    else if (f < 0.2)
        printf("it's party time");
    else
        printf("it's movie time");
  
    return 0;
}

C++

// C++ program to illustrate the above idea
#include 
using namespace std;
  
// Driver Code
int main()
{
    float f = 0.2;
  
    // Declare a variable with very small value
    // float acceptableDifference = 1e-9;
    float acceptableDifference = 0.00000001;
  
    // Check if the diff of both values is
    // less than this variable
    if (abs(f - 0.2) < acceptableDifference)
        cout << "it's geek time";
    else if (f < 0.2)
        cout << "it's party time";
    else
        cout << "it's movie time";
    return 0;
}
输出:
it's geek time

注意:当不需要更改程序中任何位置的任何变量的数据类型时,首选最后一种方法,否则也可以遵循上述列出的任何方法,因为它们简单、简短且不那么复杂。在比较 if 语句中的浮点数时要格外小心和小心。

想要从精选的视频和练习题中学习,请查看 C 基础到高级C 基础课程。