I want to convert float to int removing decimal point, meaning if F = 2.521, conversion to int = 2521 What is the fast way to do this using C++?
            Asked
            
        
        
            Active
            
        
            Viewed 1,172 times
        
    0
            
            
        - 
                    5`round(F * 1000.0)`. Note with `float F = 2.521;` , `F` is not _exactly_ 2.521. – chux - Reinstate Monica Jul 05 '21 at 02:34
- 
                    2Use strings. For the good fraction of floating point numbers, they cant be represented exactly: https://stackoverflow.com/questions/588004/is-floating-point-math-broken – NathanOliver Jul 05 '21 at 02:34
- 
                    Further to the what chux said above, the rounding modes are: std::ceil, std::floor, std::trunc, or std::round. round is the most common, but might not be exactly what you need. – robthebloke Jul 05 '21 at 02:35
- 
                    1What's the source of these floats? Should `2.5` be mapped to `25` and `2.52` mapped to `252`? If so you might run into some precision issues where things that have a short exact representation in decimal _don't_ have one in binary. – Nathan Pierson Jul 05 '21 at 02:37
- 
                    Hmm, strings are probably slow, but I like rounding method. – G.Azma Jul 05 '21 at 02:38
- 
                    I want floats to be mapped to it's lowest decimal (not counting super low floating point errors) – G.Azma Jul 05 '21 at 02:38
- 
                    Strings are slow... sometimes. Depends a lot on what you're going to do with them. I find that unless I'm doing arithmetic with numbers, strings work faster and easier. – user4581301 Jul 05 '21 at 02:43
- 
                    @G.Azma: When you say "mapped to lowest decimal" do you mean "rounded towards negative infinity" (e.g. -5.250000000001 becomes -526) or "rounded towards zero" (e.g. -5.250000000001 becomes -525) or do you mean "not rounded in the first place" (e.g. -5.250000000001 becomes -5250000000001)? – Brendan Jul 05 '21 at 02:47
- 
                    @G.Azma What if the value was 2.520999908447265625? This is a value `float` can exactly encode. Would you want `2520999908447265625` to print out as the integer or `2521` or `2520` or ??? – chux - Reinstate Monica Jul 05 '21 at 02:47
- 
                    I want 2.515715 to print out 2515715, but 1.15151519581011 not, it's too low – G.Azma Jul 05 '21 at 02:52
- 
                    @G.Azma A `float` cannot encode 2.515715. The nearest `float` is 2.5157148838043212890625. What should that print out? – chux - Reinstate Monica Jul 05 '21 at 02:55
- 
                    Sorry, I am not familiar with how floats work, comment about rounding answered my question, I wanted to map float to int from start to end (8 decimal places, or something reasonable like that, so I can just multiply float by 1e8) – G.Azma Jul 05 '21 at 02:58
- 
                    1@G.Azma: Do you mean "no more than 8 fractional digits" (e.g. 123456789123456789.0 becomes 123456789123456789) or do you mean "no more than 8 significant digits (e.g. 123456789123456789.0 becomes 12345678)? Note that the former may cause problems with overflowing the resulting integer. – Brendan Jul 05 '21 at 03:00
- 
                    8 significant digits – G.Azma Jul 05 '21 at 03:02
3 Answers
0
            
            
        I have no idea if it's the fastest way (or merely "a way"), and haven't tested if it behaves as I intend (especially with regard to precision loss), but here's my attempt at "extract up to 8 significant decimal digits from float into integer, with trailing zero suppression and rounding towards zero"):
#include <math.h>
int32_t convert(float value) {
    double v = value;     // Need to increase size to reduce risk of precision loss
    int sign = 0;
    int32_t result = 0;
    int digit;
    // Extract sign and ensure v isn't negative
    if(v < 0) {
        sign = 1;
        v = -v;
    }
    // Reduce magnitude of v by dividing by 10 until it's between 0.0 and 1.0 (exclusive).
    while(v >= 100000000.0) {
         v /= 1000000000.0;
    }
    if(v >= 10000.0) {
         v /= 100000.0;
    }
    if(v >= 100.0) {
         v /= 1000.0;
    }
    if(v >= 10.0) {
         v /= 100.0;
    } else if(v >= 1.0) {
         v /= 10.0;
    }
    // Extract (up to) 8 significant digits from v while trying to avoid trailing zeros (e.g. the original value 1.2 would hopefully become 12 and not 12000000).
    for(int i = 0; (i < 8) && ((float)v > 0.0); i++) {
        digit = floor(v * 10);
        result = result*10 + digit;
        v = v * 10 - digit;
    }
    // Suppress any trailing zeros that slipped through due to precision losses
    while( (result != 0) && (result % 10 == 0) ) {
        result /= 10;
    }
    // Restore the original value's sign
    if(sign != 0) {
         result = -result;
    }
    // Done!
    return result;
}
 
    
    
        Brendan
        
- 35,656
- 2
- 39
- 66
0
            
            
        i did this with string input of float number.put the string chars into integer array except '.' and then convert integer array into decimal number in base 10.
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
int main()
{
    string str="";
    cout<<"Enter num ?\n";
    cin>>str;
    int k = str.length()-1;
    int *a  = new int[k];
    int x=0;
    for(int i=0;i<str.length();i++)
    {
        if(str[i]!='.')
        a[x++] = (int(str[i]))-48;
        
    }
    long int res=0;
    x=0;
    for(int i=0;i<k;i++)
    {
        res+=a[k-1-i]*pow(10,x++);
    }
    cout<<"Integer is = "<<res<<endl;
}
 
    
    
        Salar Ashgi
        
- 128
- 2
- 13
- 
                    `int *a = new int[k]` instead of `std::vector`, and no `delete[]` - this is not exactly a good example of C++ in the 21st century. – MSalters Jul 05 '21 at 09:28
0
            
            
        for (; std::trunc(f) != f; f *= 10);
std::intmax_t const i(f);
Note, that there may still be UB as the range of floats is very large and you obviously need a signed integral type. Note that floats are usually not decimal.
 
    
    
        user1095108
        
- 14,119
- 9
- 58
- 116
