7

サンプルコード:浮動小数点値を123.3443〜1233443のような正確な精度の整数に変換する方法はありますか?

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

数字が「1.999999999999」の場合はどうなりますか?ヒント:あなたがしようとしていることは不可能です。 (あるいは、少なくともバイナリ浮動小数点ではあまり定義されていません) – Mysticial

+0

おそらく、ゼロに近い(許容度を持つ)部分の左にある浮動小数点数を得ることでしょうか? – markw

+0

@Mysticial:FP指数が2の累乗であるため、実際には浮動小数点で常に可能です。通常、結果はあなたの望むものではありません(たとえば、正確なバイナリ分数の場合のみ)。 – duskwuff

答えて

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

本当に役に立たない答え(質問者は彼が求めたものを正確に得ることができます)。おそらく彼が心に持っていたものではないでしょう。 – AoeAoe

0

乗算floatxは、小数点の後にあなたがしたいと、その後intにキャストどのように多くの桁である10^xによります。

+0

これは動作しますが、あらかじめ必要な小数点以下の桁数を知っていることを前提としています。 – PeterAllenWebb

10

123.3443は、32ビット浮動小数点数では正確には16166984/131072と表されます。実際には123.34429931640625で、123.3443ではありません。

これが本当に望む結果なら(おそらくそうではないかもしれませんが)、IEEE-754浮動小数点演算がどのように機能するかを見て、好きな任意の値を取り出して、高精度の数学スイートです。 「舞台裏で」何が起こっているのかを理解したら、正確な表現を生成することはでもではありません。 「十分に近い」表現を生成することは実際はずっと困難です。あなたが変換された数の任意の繰り返し処理を行う必要はありませんし、唯一の整数に数値を変換するために探している場合:)

-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

floatf

float f=123.456; 

の整数当量がmodff()

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

を用いて製造することができる今integral(123.000000のような)整数部を有し、fractionalは小数を有します一部(0.456000など)。

浮動小数点数(この場合はf)が負の場合、integralfractionalの両方が負の値になります。

あなたはそれを改善するために

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

を行うことができます。

さて、

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

%g書式指定子は、末尾のゼロを削除し、tempは今"0.456"を持つことになります。

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

小数部分が0であれば、それは0なく0.000000してきたと同じようにfractionalを印刷中にあるため、何の小数点がなかっwould'v。 tempの2番目の文字が.ではない場合、fractionalはゼロであり、それを気にする必要はありません。

今の場合、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に格納することができる場合(これはlimits.hに'S)最初long intstrtol()によって返される値を格納し、それは、INT_MAXよりも大きいかどうか、確認するに

結果の精度は、浮動小数点数が2進数で表される精度に依存することに注意してください。

関連する問題