2009-02-01 23 views
38

¿Cómo podemos extraer la parte decimal de un número de coma flotante y almacenar la parte decimal y la parte entera en dos variables enteras separadas?Extrae la parte decimal de un número de coma flotante en C

+0

Cómo/¿por qué quiere representar la parte fraccionaria en un entero? –

+5

¿Cómo distinguirías las fracciones decimales en 1.5 y 1.005? – SingleNegationElimination

+0

No veo cómo podría poner la parte decimal en un número entero a menos que sepa cuántos dígitos quería conservar. ¿Podría dar algunos ejemplos? – Nosredna

Respuesta

76

se utiliza la función modf:

double integral; 
double fractional = modf(some_double, &integral); 

También se puede convertir en un entero, pero se advirtió que puede desbordar el número entero. El resultado no es predecible entonces.

+1

http://codepad.org/A0ilp9eE Parece que no funciona – penu

+1

@penu Es porque está utilizando '% d' para imprimir' double'. Aquí está el código de trabajo: http://codepad.org/kPGKtcZi –

38

Prueba esto:

int main() { 
    double num = 23.345; 
    int intpart = (int)num; 
    double decpart = num - intpart; 
    printf("Num = %f, intpart = %d, decpart = %f\n", num, intpart, decpart); 
} 

Para mí, se produce:

Num = 23.345000, intpart = 23, decpart = 0.345000 

que parece ser lo que estás pidiendo.

+1

la primera parte es correcta pero desea obtener el resultado como una parte decimal como 345000 entero – Binu

+1

pero quiero obtener la parte deciaml como valor entero que significa decpart = 345000 – Binu

+1

int decpart = 100000 * (num - intpart); – SingleNegationElimination

1

Creé una subrutina utilizando un flotador doble, devuelve 2 valores enteros.


void double2Ints(double f, int p, int *i, int *d) 
{ 
    // f = float, p=decimal precision, i=integer, d=decimal 
    int li; 
    int prec=1; 

    for(int x=p;x>0;x--) 
    { 
    prec*=10; 
    }; // same as power(10,p) 

    li = (int) f;    // get integer part 
    *d = (int) ((f-li)*prec); // get decimal part 
    *i = li; 
} 

void test() 
{ 
    double df = 3.14159265; 
    int i,d; 
    for(int p=2;p<9;p++) 
    { 
    double2Ints(df, p, &i,&d); printf("d2i (%d) %f = %d.%d\r\n",p, df,i,d); 
    } 
} 
 
12

La rápida "en una cáscara de nuez" respuesta más obvia parece como:

#define N_DECIMAL_POINTS_PRECISION (1000) // n = 3. Three decimal points. 

float f = 123.456; 
int integerPart = (int)f; 
int decimalPart = ((int)(f*N_DECIMAL_POINTS_PRECISION)%N_DECIMAL_POINTS_PRECISION); 

que iba a cambiar el número de decimales que desee cambiando el N_DECIMAL_POINTS_PRECISION para satisfacer sus necesidades.

+1

Solo por diversión. Vamos a hacer un experimento de pensamiento: La solución más ofuscada y compleja (ver "código difícil de mantener") podría ir tan lejos como [bit slicing] [1] el float o double para obtener los ["integerBits" y "fractionalBits" reales. "] [2]. –

+0

No estoy exactamente seguro de por qué harías esto ...quizás este método tenga la ventaja de capturar el entero y las partes decimales directamente sin perder la precisión debido al redondeo de coma flotante. –

+0

Aquí hay un código de pseudo incompleta para darle la idea: #define BIT_MASK1/* no está seguro */#define SHIFT/* no está seguro */#define BIT_MASK2/* * no está seguro/ float f = 123.456 ; uint32_t * tmp = (uint32_t *) & f; int integerPart = (int) f; –

-1

Quizás la mejor idea es resolver el problema mientras los datos están en formato de cadena. Si tiene los datos como Cadena, puede analizarlos de acuerdo con el punto decimal. Extrae la parte integral y decimal como subcadenas y luego convierte estas subcadenas en enteros reales.

+0

Convertirlo en una cadena solo para esto es un poco tonto, pero si originalmente fuera una cuerda, esto tiene sentido. –

+0

Como se mencionó anteriormente, considere 1.5 y 1.005 ... – Mikhail

-1

Hice esta función, parece que funciona bien:

#include <math.h> 

void GetFloattoInt (double fnum, long precision, long *pe, long *pd) 
{ 
    long pe_sign; 
    long intpart; 
    float decpart; 

    if(fnum>=0) 
    { 
    pe_sign=1; 
    } 
    else 
    { 
    pe_sign=-1; 
    } 

    intpart=(long)fnum; 
    decpart=fnum-intpart; 

    *pe=intpart; 
    *pd=(((long)(decpart*pe_sign*pow(10,precision)))%(long)pow(10,precision)); 
} 
0

Aquí es otra manera:

#include <stdlib.h> 
int main() 
{ 
    char* inStr = "123.4567";   //the number we want to convert 
    char* endptr;      //unused char ptr for strtod 

    char* loc = strchr(inStr, '.'); 
    long mantissa = strtod(loc+1, endptr); 
    long whole = strtod(inStr, endptr); 

    printf("whole: %d \n", whole);  //whole number portion 
    printf("mantissa: %d", mantissa); //decimal portion 

} 

http://codepad.org/jyHoBALU

Salida:

whole: 123 
mantissa: 4567 
+0

Su código no funcionará en plataformas de 16 bits donde longs son 32 bits y long double son 53 bits. – user2284570

3

creo que usando string es la forma correcta de proceder en este caso, ya que no se conoce a priori el número de dígitos en la parte decimal. Sin embargo, no funcionará para todos los casos (por ejemplo, 1.005), como se mencionó anteriormente por @SingleNegationElimination. Aquí está mi opinión sobre esto:

#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
{ 
    char s_value[60], s_integral[60], s_fractional[60]; 
    int i, found = 0, count = 1, integral, fractional; 

    scanf("%s", s_value); 

    for (i = 0; s_value[i] != '\0'; i++) 
    { 
     if (!found) 
     { 
      if (s_value[i] == '.') 
      { 
       found = 1; 
       s_integral[i] = '\0'; 
       continue; 
      } 
      s_integral[i] = s_value[i]; 
      count++; 
     } 
     else 
      s_fractional[i - count] = s_value[i]; 
    } 
    s_fractional[i - count] = '\0'; 

    integral = atoi(s_integral); 
    fractional = atoi(s_fractional); 
    printf("value = %s, integral = %d, fractional = %d\n", 
     s_value, integral, fractional); 

    return 0; 
} 
0

Si solo quiere obtener el primer valor decimal, la solución es realmente simple.

He aquí un ejemplo explicativo:

int leftSideOfDecimalPoint = (int) initialFloatValue; // The cast from float to int keeps only the integer part 

int temp = (int) initialFloatValue * 10; 
int rightSideOfDecimalPoint = temp % 10; 

decir, por ejemplo tenemos un valor flotante inicial de 27,8.

  • Con solo convertir el valor flotante inicial en un int, descarta la parte fraccionada y solo conserva la parte entera.
  • Al multiplicar el valor de flotación inicial por 10 obtenemos un resultado de 278.0, luego al convertir este resultado en int, le da el valor de 278
  • Si dividimos 278 entre 10, obtenemos 27.8, de los cuales el resto es 8, que es el valor en el lado derecho del punto decimal. Por lo tanto, use el módulo.

Esta técnica se puede utilizar para obtener los siguientes caracteres decimales utilizando, por ejemplo, 100 en lugar de 10, y así sucesivamente.


Simplemente tome en cuenta que si se utiliza esta técnica en sistemas de tiempo real, por ejemplo, para mostrarla en una pantalla de 7 segmentos, puede no funcionar adecuadamente porque estamos multiplicando con un valor de coma flotante, donde la multiplicación toma mucho tiempo de sobrecarga

-1
cout<<"enter a decimal number\n"; 
cin>>str; 
for(i=0;i<str.size();i++) 
{ 
    if(str[i]=='.') 
    break; 
} 

for(j=i+1;j<str.size();j++) 
{ 
    cout<<str[j]; 
} 
+1

¿Podría agregar algunos comentarios a su respuesta? – kvorobiev

+0

Si bien este fragmento de código puede resolver la pregunta, [incluyendo una explicación] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) realmente ayuda a mejorar la calidad de su publicación. Recuerde que usted está respondiendo la pregunta a los lectores en el futuro, y es posible que esas personas no sepan los motivos de su sugerencia de código. –

0

Incluso yo estaba pensando en cómo hacerlo. Pero encontré una manera. Prueba este código

printf("Enter a floating number"); 
scanf("%d%c%d", &no, &dot, &dec); 
printf("Number=%d Decimal part=%d", no, dec); 

de salida: -

Enter a floating number 
23.13 
Number=23 Decimal part=13 
Cuestiones relacionadas