How to get the exact fractional part from a floating point number as an integer?

18,837

Solution 1

The easiest way is to use standard library function ceil from <math.h>.
The float number 254.73 may be converted to 254.7299957275390625000000.
f-integer will give 0.7299957275390625000000.
Now multiply it by 100 and use ceil function to get the smallest integer value not less than 72.99957275390625000000.

int fractional_part_in_integer = ((int)ceil(fractional*100)) % 100;

UPDATE: As pointed in a comment by @Sneftel, the above suggested method in this answer will not work consistently.

A simple hack is to use round function from math.h to round the f and then extract the fractional part

float f=254.73;

int int_part = (int)f;
float fractional = round(f*100)/100 - int_part;
int fractional_part_in_integer = (int)(fractional*100);

printf("%d, %d\n ", int_part, fractional_part_in_integer);

Output:

254, 73

Solution 2

How to get the exact fractional part from a floating point number as an integer?

trying to extract the exact fractional part from a floating point number.

Use modf() or modff()

double modf(double value, double *iptr);
float modff(float value, float *iptr);

The modf functions break the argument value into integral and fractional parts, ...
C11 §7.12.6.12 2

#include <math.h>

double value = 1.234;
double ipart;
double frac = modf(value, &ipart);

A better approach for OP's need may be to first round a scaled value and then back into whole and fractional parts.

double value = 254.73;
value = round(value*100.0);
 
double frac = fmod(value, 100);  // fmod computes the floating-point remainder of x/y.
double ipart = (value - frac)/100.0;

printf("%f %f\n", ipart, frac);
254.000000 73.000000

Ref detail: When OP uses 254.73, this is converted to the nearest float value which may be 254.729995727539....

float f = 254.73;
printf("%.30f\n", f);
// 254.729995727539062500000000000000

Solution 3

You can use sprintf and sscanf to print the value to a string and then extract the fraction. The %*d scans and discards the first integer of the formatted string. A dot is scanned and then the fraction.

#include <stdio.h>        

int main( void)           
{                         
    char fp[30];          
    int fraction;         
    float f = 254.73f;    

    sprintf ( fp, "%.2f", f);
    sscanf ( fp, "%*d.%d", &fraction);
    printf ( "%d\n", fraction);

    return 0;                  
}
Share:
18,837
UkFLSUI
Author by

UkFLSUI

Updated on July 19, 2022

Comments

  • UkFLSUI
    UkFLSUI over 1 year

    I was trying to extract the exact fractional part from a floating point number. I tried with this:

    float f=254.73;
    
    int integer = (int)f;
    float fractional = f-integer;
    
    printf ("The fractional part is: %f", fractional);
    

    But the output is: 0.729996. For this reason when I was doing this:

    float f=254.73;
    
    int integer = (int)f;
    float fractional = f-integer;
    int fractional_part_in_integer = ((int)(f*100)%100);
    
    printf ("The value is: %d", fractional_part_in_integer);
    

    It gives me 72 as output. But, I want to extract exactly 73 from the given number 254.73. I already know how to use %.2f during printf() function to print upto two decimal numbers. But in my code I don't want to print the number right now. I have some calculations with that fractional part as integer form i.e. 73.

    So, my problem is how could I extract the fractional part from 254.73 so that I can get exact 73 as integer to do more calculations?

  • mah
    mah almost 8 years
    Would this not produce the same results the OP is already getting?
  • chux - Reinstate Monica
    chux - Reinstate Monica almost 8 years
    @mah. No. OP's method has trouble with (int)f ; fractional = f-integer; when f is out of int range, 2) f is negative 3) int has less precision that f. OP's 2nd method will likely given unsatisfactory result s with values like 1.99999
  • mah
    mah almost 8 years
    Without checking but just considering your reasoning, I believe your particular use cases are valid reasons to use your advice of fmod()... but considering the actual value the OP is using, 254.73, unless your advice solves his dilemma (which is: he expects to get back .73, and not .7299996), I think your post is a fine comment but not an answer. I'm open to being shown why I might be wrong though.
  • chux - Reinstate Monica
    chux - Reinstate Monica almost 8 years
    @mah ((int)(f*100)%100); can also suffer from f values just under a whole number, but (f*100) computes to a whole number.
  • chux - Reinstate Monica
    chux - Reinstate Monica almost 8 years
    @mah does not expect 0.73. OP expect 73. "with that fractional part as integer form i.e. 73." Rework 2nd method to do so.
  • chux - Reinstate Monica
    chux - Reinstate Monica almost 8 years
    1) This method only extracts the fractional part (as per OP's request) yet with input values like 123.996, code will render 0 for the fraction and is unclear how the whole part will be incremented to 124. 2) char fp[30]; may be too small, suggest char fp[FLT_MAX_10_EXP + 6];
  • haccks
    haccks almost 8 years
    The signature of ceil function is double ceil(double x);. It compute the smallest integer value not less than x and return ⎡x⎤. Do not forget to include #include <math.h>.
  • Sneftel
    Sneftel almost 8 years
    ceil() is just as likely to produce a number which is 1 off.
  • haccks
    haccks almost 8 years
    @Sneftel; I think its floor you are talking about. BTW, here is the demo of my solution.
  • Sneftel
    Sneftel almost 8 years
    @haccks Yeah? Try this one. Neither ceil nor floor is going to work consistently, because the value is as likely to be slightly below a multiple as 0.01 as it is to be slightly above it.
  • haccks
    haccks almost 5 years
    @Sneftel; You are right. I updated my answer. It has been fixed now.
  • Adrian Mole
    Adrian Mole over 2 years
    Recommending the use of #include <bits/stdc++.h> in an answer on Stack Overflow is asking for downvotes; use the required standard header files instead. See: stackoverflow.com/q/31816095/10871073