5

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?

UmFraWJ1bCBJc2xhbQ
  • 4,101
  • 6
  • 24
  • 41
  • 4
    Floating point numbers cannot be represented as the _exact_ value you want them to be much of the time. Your results are reasonable. A potentially interesting experiment is to print the value of `f`, which might only be close to what you think (though I've not tired myself so I'm not certain). UPDATE: I've tried it: http://ideone.com/9fbeme – mah Dec 18 '15 at 17:50
  • Thank you. But, I hope there should be a way to do some other calculations with 73 there. UPDATE: Yes, I had already done that and got that value you found in your experiment. – UmFraWJ1bCBJc2xhbQ Dec 18 '15 at 17:52
  • 2
    Since your hardware cannot represent 254.73 exactly, you're going to either have to find some other hardware that can, or use integer-based calculations instead (such as with `25473` and divide by 100 later). – mah Dec 18 '15 at 17:54
  • consider using round rather than int to truncate the number. Int will just cut off 729996 to 72 whereas round should make it 73 and be closer to what you had when you assigned it initially. Do aggre with @mah that the floating point is by nature not precise. So even this may not always work. – asantaballa Dec 18 '15 at 17:56
  • 4
    If you mean "how to get .73", you aren't ever going to get that exact value if your hardware cannot represent it. You can, however, multiply the original value (and all others you work with) by 100, work with them at this level (where the representation is exactly 100 times what you need the values to be) and later divide by 100 to get your exact result (still, limited by what your hardware can represent). – mah Dec 18 '15 at 18:01
  • Just to add some suggestion on how to do that, as I don't know, can't I scan any floating point number to some specific decimal points, for example: it will only scan up to two decimal not more than that. – UmFraWJ1bCBJc2xhbQ Dec 18 '15 at 18:01
  • 2
    @RakibulIslam Now that I understand the problem you're trying to solve a little better, I think your best bet here is to split the _string_ data up the way user3121023 suggests in his answer. That would give you two integer values, 254 and 73, which you could then process as you seem to already be doing. Just process the "partial dollar" value as an integer (that you expect to be between 0 and 99) rather than as a floating point value. – mah Dec 18 '15 at 18:16

4 Answers4

10

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
Community
  • 1
  • 1
chux - Reinstate Monica
  • 113,725
  • 11
  • 107
  • 213
  • 2
    Would this not produce the same results the OP is already getting? – mah Dec 18 '15 at 17:59
  • 1
    @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 – chux - Reinstate Monica Dec 18 '15 at 18:10
  • 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. – mah Dec 18 '15 at 18:12
  • @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 Dec 18 '15 at 18:13
  • @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 Dec 18 '15 at 18:22
2

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;                  
}
user3121023
  • 6,995
  • 5
  • 14
  • 13
  • 3
    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];` – chux - Reinstate Monica Dec 18 '15 at 18:28
0

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
haccks
  • 97,141
  • 23
  • 153
  • 244
  • 1
    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 `. – haccks Dec 18 '15 at 20:23
  • 1
    `ceil()` is just as likely to produce a number which is 1 off. – Sneftel Dec 18 '15 at 21:45
  • @Sneftel; I think its `floor` you are talking about. BTW, here is the [demo](https://ideone.com/wHc7I3) of my solution. – haccks Dec 18 '15 at 21:51
  • 3
    @haccks Yeah? Try [this one](https://ideone.com/yeay8O). 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. – Sneftel Dec 18 '15 at 22:39
  • 3
    @Sneftel; You are right. I updated my answer. It has been [fixed](https://ideone.com/wDuXan) now. – haccks Nov 12 '18 at 08:29
-2

Take the number in string use the built-in function find() to find the position of ".".

#include <iostream>
using namespace std;

int main()
{    
    string f = "254.7356656";    
    int position = f.find(".");    
    cout << f.substr(position + 1);    
    return 0;    
}

Output: 7356656

Ananth
  • 1
  • 2
  • Recommending the use of `#include ` in an answer on Stack Overflow is asking for downvotes; use the required *standard* header files instead. See: https://stackoverflow.com/q/31816095/10871073 – Adrian Mole Mar 28 '21 at 12:18