Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check value after a decimal point [duplicate]

Tags:

c++

I have the following list of numbers, they are sent one by one to a function.

96.487587
96.561569
97.893280
97.967270
98.041245
98.115227
98.855072
98.929054
99.003044
99.890846
99.964836

How do I check if the value after the dot is 0, for example:

99.003044 or 98.041245
like image 390
Stan Avatar asked Aug 08 '19 19:08

Stan


4 Answers

Because modf returns the fractional part with the same sign as its argument, use the absolute value of the fraction for testing:

#include <cmath>

bool check(double x)
{
    double integral, fractional;
    fractional = std::modf(x, &integral);
    return std::abs(fractional) < 0.1;
}
like image 137
Michael Roth Avatar answered Sep 23 '22 19:09

Michael Roth


There are a couple ways you can do this. First, you can use std::modf and test if the return value, which is the decimal part, is less than .1. That would look like

bool check(double value)
{
    double discard;
    return std::abs(std::modf(value, &discard)) < .1;
    // need the abs for cases when value is negative.
}

Another option would be to subtract the whole part out of the value and see if that is less than .1. You can do that using std::floor like

bool check(double value)
{
    return (value - std::floor(value)) < .1;
}

Do note that at least for some values both of thses solutions fail because of floating point inaccuracy. To avoid that you can use the bullet proof solution of converting the value to a string, and then testing if there is a 0 after the decimal point. That would look like

bool check(double value)
{
    std::string str = std::to_string(value);
    size_t pos = str.find(".");
    if (pos == std::string::npos)
        return true; // not sure if you want to return true or false for whole numbers
    return str[pos + 1] == '0';
}
like image 35
NathanOliver Avatar answered Sep 23 '22 19:09

NathanOliver


The only 100% safe way of doing this is to extract this information from the double value itself. Multiplications by 10 (as suggested in the comments) can lead to numerical overflow, as well as getting integer part of the value by casting to integer.

Luckily, C++ has the facilities for that, std::modf. It gives you fractional part of the double number, which you can than compare with 0.1.

(As other answer suggests, you can also use std::floor).

like image 32
SergeyA Avatar answered Sep 21 '22 19:09

SergeyA


It seems that most of the solutions given won't work for the input 10.1. Here's what I have achieved:

Code:

#include <iostream>
#include <string>
#include <cmath>    // std::abs

void isZero(double x){
    double total = std::abs (x) - std::abs((int)x);
    //std::cout << "Decimal Number: " << total << "\n";
    if(((total * 10 + 0.5) / 10.0) < 0.10){
        std::cout << x << " True\n";
    }else{
        std::cout << x << " False\n";
    }
}

int main(){
    double positive[] = { 
        96.487587, 96.561569, 97.893280, 97.967270, 
        98.041245, 98.115227, 98.855072, 98.929054, 
        99.003044, 99.890846, 99.964836, 10.0, 10.1, 
        10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9,
    };
    double negative[] = { 
        -96.487587, -96.561569, -97.893280, -97.967270, 
        -98.041245, -98.115227, -98.855072, -98.929054, 
        -99.003044, -99.890846, -99.964836, -10.0, -10.1, 
        -10.2, -10.3, -10.4, -10.5, -10.6, -10.7, -10.8, -10.9
    };

    for(int i = 0; i <  sizeof(positive)/sizeof(positive[0]); i++){
        isZero(positive[i]);
    }

    for(int i = 0; i <  sizeof(negative)/sizeof(negative[0]); i++){
        isZero(negative[i]);
    }
}

Output:

96.4876 False
96.5616 False
97.8933 False
97.9673 False
98.0412 True
98.1152 False
98.8551 False
98.9291 False
99.003 True
99.8908 False
99.9648 False
10 True
10.1 False
10.2 False
10.3 False
10.4 False
10.5 False
10.6 False
10.7 False
10.8 False
10.9 False
-96.4876 False
-96.5616 False
-97.8933 False
-97.9673 False
-98.0412 True
-98.1152 False
-98.8551 False
-98.9291 False
-99.003 True
-99.8908 False
-99.9648 False
-10 True
-10.1 False
-10.2 False
-10.3 False
-10.4 False
-10.5 False
-10.6 False
-10.7 False
-10.8 False
-10.9 False
like image 20
M. Al Jumaily Avatar answered Sep 21 '22 19:09

M. Al Jumaily