7
kod

Próbka:Jak przekonwertować wartość pływającą na liczbę całkowitą z dokładnością taką jak 123.3443 do 1233443?

int main() { 
    float f = 123.542; 
    int i = (int)f; 
    printf("%d\n",i); 
} 
+2

Co zrobić, jeśli numer to '1.999999999999'? Wskazówka: to, co próbujesz, nie jest możliwe. (lub przynajmniej jest źle zdefiniowany z binarnym zmiennoprzecinkowym) – Mysticial

+0

Być może chcesz, aby po lewej stronie jakiejś części, która jest bliska zeru (z pewną tolerancją), pojawi się tak duży ruch? – markw

+0

@Mysticial: W praktyce zawsze jest to możliwe z zmiennoprzecinkowym, ponieważ wykładnik FP ma potęgę 2. Wyniki zwykle nie są tym, czego potrzebujesz (np. Działa tylko dla dokładnych frakcji binarnych). – duskwuff

Odpowiedz

2
int i = (int) (f * 10000 + 0.5); 
+2

Niezbyt pomocna odpowiedź (choć pytający dostałby dokładnie to, o co prosił). To (bardzo) prawdopodobnie nie to, co miał na myśli. – AoeAoe

0

Pomnóż float przez 10^x gdzie x to ile cyfr po przecinku chcesz, a następnie przesyłać int.

+0

To zadziała, ale zakłada, że ​​znasz liczbę miejsc dziesiętnych, które chcesz z góry. – PeterAllenWebb

10

123.3443 nie może być dokładnie reprezentowany przez liczbę zmiennoprzecinkową - w 32-bitowym float jest skutecznie reprezentowany jako 16166984/131072, który w rzeczywistości jest 123.34429931640625, a nie 123.3443. (Jest wyłączony o około 6,8 x 10^-7.)

Jeśli naprawdę jest to pożądany rezultat (co prawdopodobnie nie jest), sprawdź, jak działają wskaźniki IEEE-754 i wyciągnij ulubione arbitralne- precyzyjny pakiet matematyki. Gdy zrozumiesz, co dzieje się "za kulisami", generowanie dokładnej reprezentacji nie powinno być zbyt trudne. Generowanie "wystarczająco dokładnej" reprezentacji zaokrąglonej jest w rzeczywistości o wiele trudniejsze. :)

-1
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int f2i(float v, int size, int fsize){ 
    char *buff, *p; 
    int ret; 
    buff = malloc(sizeof(char)*(size + 2)); 
    sprintf(buff, "%*.*f", size, fsize, v); 
    p = strchr(buff, '.'); 
    while(*p=*(p+1))p++; 
    ret = atoi(buff); 
    free(buff); 
    return ret; 
} 

int main(){ 
    float f = 123.3443; 

    printf("%d\n", f2i(f, 7, 4)); 

    f=123.542; 
    printf("%d\n", f2i(f, 6, 3)); 
    return 0; 
} 
0

Jeśli nie trzeba robić żadnych powtarzalnych przetwarzanie liczby przebudowanej i szukasz tylko do konwersji liczb do liczby całkowitej, najprostszym sposobem jest użycie sprintf, a następnie zsumować dziesiętne z pętla for używająca mocy 10 reguł. Jeśli potrzebujesz "dokładnej precyzji" do matematyki, użyj BCD. Poniższy algorytm pozwoli ci obcinać liczbę cyfr dla "dokładnej precyzji".

#include "math.h" 

long ConvertToScaledInteger (float value, int significantDigits = -1) 
{ 
    // Note: for 32-bit float, use long return and for double use long long. 

    if (significantDigits < 1) // Ditch the '-' and the '.' 
     significantDigits += 2; 
    else 
     ++significantDigits;  // Ditch the '.' 

    char* floatingPointString = malloc(sizeof (char) * (4 + FLT_MANT_DIG - FLT_MIN_EXP)); 
    /*< This solution is for a 32-bit floating point number. Replace FLT 
     with DBL, and it will produce the max number of chars in a 64-bit 
     float string. */ 

    if (significantDigits < 0) //< Then use all of the float's digits. 
    { 
     sprintf (floatingPointString , "%f", floatingPointNumber); 
    } 
    else //< Then truncate the number of decimal places. 
    { 
     char decimalPlaceString[9]; 
     char percentString = "%\0"; 
     sprintf (decimalPlaceString, "%s%if", percentString , significantDigits); 
     sprintf (floatingPointString , decimalPlaceString, value); 
    } 

    int stringLength = strlen (floatingPointString), 
     index; 
    long returnValue = 0; 
    double powerOfTen = 10.0, 
     currentValue; 

    // Find if we have an ending of .0, and backtrack. 
    if (floatingPointString[stringLength - 1] == '0' && floatingPointString[stringLength - 2] == '.') 
     index = stringLength - 3; 
    else 
     index = stringLength - 1; 

    for (; index > 0; --index) 
    { 
     if (floatingPointString[index] == '.') 
      --index; 

     // Subtract ASCII '0' converts ASCII to integer. 

     currentValue = (double) floatingPointString[index] - '0'; 
     returnValue += (long) currentValue * pow (10.0, powerOfTen); 

     powerOfTen += 1.0; 
    } 

    if (floatingPointString[0] == '-') 
     returnValue *= -1; 

    return returnValue; 
} 
+0

Po co odpowiadać za pomocą kodu C++ dla wpisu C? Polecam przeniesienie do C. – chux

+0

'4 + FLT_MANT_DIG - FLT_MIN_EXP' jest za małe. Zobacz [komentarz] (http://stackoverflow.com/questions/9644327/how-to-convert-floating-value-to-integer-with-exact -precision- like-123-3443-to-1#comment53280321_32674012) – chux

+0

'" \ %% if "' invalid sequence sequence. – chux

0

Równoważnik całkowitą z float liczby f

float f=123.456; 

mogą być wykonane z użyciem modff() jak

float integral, fractional; 
char str[50], temp[20]; 
fractional = modff(f, &integral); 

Teraz integral ma część całkowita (jak 123.000000) i fractional ma ułamkową część (jak 0,456000).

Jeśli liczba zmiennoprzecinkowa (f w tym przypadku) była ujemna, zarówno integral, jak i fractional były ujemne.

Można zrobić

if(fractional<0) 
{ 
    fractional = -fractional; 
} 

do naprawienia tego.

Teraz

sprintf(temp, "%g", fractional); 

%g Format specifier usunie końcowe zera i temp mają teraz "0.456".

sprintf(str, "%g%s", integral, temp[1]=='.'?temp+2:""); 

The temp[1]=='.'? się tak dlatego, jeśli część ułamkowa były 0 istnieje would'v było żadnego punktu dziesiętnego podczas drukowania fractional gdyż byli 0 a nie 0.000000. Jeśli drugi znak w temp nie jest równy zero i nie musimy się nim przejmować.

Teraz w naszym przypadku str będzie "123456". Ale to jest w formie sznurka. Musimy przekonwertować go na liczbę całkowitą. Użyj do tego celu strtol().

long l=strtol(str, NULL, 10); 
if(l>INT_MAX || errno==ERANGE) 
{ 
    printf("\noverflow"); 
} 
else 
{ 
    printf("\n%d", strtol(str, NULL, 10)); 
} 

Można sprawdzić wartość zwracaną strtol() i że od errno (od errno.h. Sprawdź, czy jest ERANGE), aby sprawdzić, czy wystąpiło przepełnienie.

Aby sprawdzić, czy wartość wypadkowa może być przechowywany w int najpierw zapisanie wartości powrotu strtol() w long int i sprawdzić, czy jest większa niż INT_MAX (jest w limits.h).

Należy zauważyć, że dokładność wyniku zależy od dokładności, z jaką liczba zmiennoprzecinkowa jest reprezentowana w postaci binarnej.

Powiązane problemy