7

샘플 코드 : 많은 숫자가 소수점 후 원하는 다음 int 캐스팅 방법123.3443에서 1233443과 같은 정확한 정밀도로 부동 값을 정수로 변환하는 방법은 무엇입니까?

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

숫자가 '1.999999999999'이면 어떻게 될까요? 힌트 : 당신이하려는 것은 불가능합니다. (또는 적어도 이진 부동 소수점으로 잘못 정의 된 경우) – Mysticial

+0

아마도 원하는 부분은 0에 가까운 일부 부분의 왼쪽에 많은 공차를 얻는 것입니다 (허용 오차가 있음)? – markw

+0

@Mysticial : FP 지수는 2의 거듭 제곱이므로 실제로 부동 소수점을 사용할 수 있습니다. 보통 결과는 원하는 바가 아닙니다 (예 : 정확한 바이너리 분수에만 적용됨). – duskwuff

답변

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

정말 도움이되는 대답은 아닙니다. (질문자가 정확히 무엇을 요구했는지는 알지만). 그것은 아마도 그가 생각한 바가 아닐 것입니다. – AoeAoe

0

곱하기 xfloat10^x가있는 곳.

+0

이 방법은 효과가 있지만 사전에 원하는 소수 자릿수를 알고 있다고 가정합니다. – PeterAllenWebb

10

123.3443은 부동 소수점 숫자로 정확하게 표현 될 수 없습니다. 32 비트 부동 소수점에서는 16166984/131072으로 표시되며 실제로는 123.34429931640625가 아니라 123.3443입니다.

이것이 실제로 원하는 결과라면 IEEE-754 플로트가 어떻게 작동하는지 살펴보고 마음에 드는 임의 코드를 꺼내십시오 (이 코드는 약 6.8 x 10^-7 정도입니다) 정밀 수학 제품군. "배경"에서 일어나는 일을 이해하면 정확한 표현을 생성하는 것이 이 아니어야합니다.입니다. "충분히 가깝게"둥근 표현을 생성하는 것은 사실 훨씬 더 어렵습니다. 변환 된 숫자의 반복 처리를 수행 할 필요가 없습니다 만 정수로 숫자를 변환하고자하는 경우 :

-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

는 가장 쉬운 방법은 다음의 sprintf를 사용하여 진수를 요약하는 것입니다 10 규칙의 힘을 사용하는 for 루프. 수학에 "정확한 정밀도"가 필요한 경우 BCD를 사용하십시오. 다음 알고리즘을 사용하면 "정확한 정밀도"의 자릿수를자를 수 있습니다.

#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

왜 C 게시물에 대한 C++ 코드로 대답합니까? C로 이식을 권장합니다. – chux

+0

'4 + FLT_MANT_DIG - FLT_MIN_EXP'가 너무 작습니다. [주석] (http://stackoverflow.com/questions/9644327/how-to-convert-floating-value-to-integer-with-exact-precision-like-123-3443-to-1#comment53280321_32674012) – chux

+0

을 참조하십시오. ' "\ %%" "이스케이프 시퀀스가 ​​잘못되었습니다. – chux

0

지금

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

integralmodff()를 사용 f

float f=123.456; 

이 이루어질 수 float 숫자의 정수 당량 (123.000000 같은) 정수 부분을 가지며 fractional는 부분을 갖는다 부분 (예 : 0.456000).

부동 소수점 숫자 (이 경우 f)가 음수이면 integralfractional이 모두 음수입니다.

당신은

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

가를 해결하기 위해 할 수 있습니다. 이제

,

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

%g 형식 지정자가 후행 0을 제거하고 temp 지금 "0.456"있을 것이다. fractional이 있었던 것처럼 0하지 0.000000를 인쇄하는 동안

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

temp[1]=='.'?

는 소수 부분이 0이었다 때문에 경우에 행해진 다, 더 소수점이 없었다 would'v. temp의 두 번째 문자가 .이 아닌 경우 fractional은 0이며이를 신경 쓸 필요가 없습니다.

이제 우리의 경우 str"123456"이됩니다. 그러나 그것은 문자열 형태입니다. 이것을 정수로 변환해야합니다. 이를 위해서는 strtol()을 사용하십시오.

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

당신은 (. errno.h에서이 ERANGE 있는지 확인) 반환 strtol()의 가치와 errno의를 확인 오버 플로우가 발생하면 볼 수 있습니다. 결과치가 int에 저장 될 수있는 경우

먼저 long int strtol()에 의해 리턴 된 값을 저장하고 그보다 INT_MAX 인 경우 (이것은 limits.h에있어)를 참조하기 위해 참조.

결과의 정확도는 부동 소수점 숫자가 2 진수로 표현되는 정확도에 따라 달라집니다.