2013-07-27 2 views
0
  • Платформа: Linux 3.2.0 (Debian 7.0)
  • Компилятор: GCC 4.7.2 (Debian 4.7.2-5)

Я пытаюсь преобразовать строку символов в поплавках , Я знаю, что уже есть функции, которые делают это. Я делаю это только для практики. Моя функция хорошо работает с простыми цифрами, такими как 123.123, 1234, -678.8. Но когда я пытаюсь преобразовать строку .99999999 в float, я получаю 1. Что явно проблема. Я не знаю, связано ли это с тем, что .99999999 не может быть выражено с помощью float или если я что-то делаю неправильно. Вопрос, который я задаю, заключается в том, как я могу вычислить максимальную долю, которую может выражать float. Как я, из-за отсутствия лучшего термина, знаю, когда поплавок вот-вот переполнится?Max Float Фракция

Вот что у меня есть.

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

int cstrtof(const char *cstr, float *f); 
int cstrtof(const char *cstr, float *f) 
{ 
unsigned short int i = 0; 
unsigned short int bool_fraction = 0; 
float tmp_f = 0; 

if(cstr[0] == '\000') return -1; 
else if(cstr[0] == '-') i = 1; 

for(; cstr[i] != '\000'; i++) 
{ 
    printf("tmp_f = %f\n", tmp_f); 
    if(cstr[i] >= '0' && cstr[i] <= '9') 
    { 
     if(tmp_f > (FLT_MAX - (cstr[i] - '0'))/10) return -2; 
     else tmp_f = tmp_f * 10 + (cstr[i] - '0'); 
    } 
    else if(cstr[i] == '.') bool_fraction = i+1; 
    else return i+1; 
} 

printf("tmp_f = %f\nbool_fraction = %i\n", tmp_f, bool_fraction); 

if(bool_fraction) 
{ 
    for(bool_fraction--; bool_fraction < i-1; bool_fraction++, tmp_f /= 10) 
    { 
     printf("tmp_f = %f\n", tmp_f); 
    } 
} 

printf("tmp_f = %f\nbool_fraction = %i\n", tmp_f, bool_fraction); 

if(cstr[0] == '-') *f = tmp_f*-1; 
else *f = tmp_f; 

return 0; 
} 

int main(int argc, char *argv[]) 
{ 
float f = 0; 
int return_value = 0; 

return_value = cstrtof(argv[1], &f); 
if(return_value == 0) 
{ 
    printf("f = %.11f\n", f); 
} 
else if(return_value == -1) 
{ 
    printf("ERROR Empty String\n"); 
} 
else if(return_value == -2) 
{ 
    printf("ERROR Data Type Overflow\n"); 
} 
else 
{ 
    printf("ERROR Invalid character '%c'\n", argv[1][return_value-1]); 
} 

return 0; 
} 

Также cstrtof() основан на следующей функции.

int cstrtoslli(const char *cstr, signed long long int *slli) 
{ 
unsigned short int i = 0; 
signed long long int tmp_slli = 0; 

if(cstr[0] == '\000') return -1; 
else if(cstr[0] == '-') i = 1; 
else if(cstr[0] == '0') return -2; 

for(; cstr[i] != '\000'; i++) 
{ 
    if(cstr[i] >= '0' && cstr[i] <= '9') 
    { 
       //LLONG_MAX is defined in limits.h 
     if(tmp_slli > (LLONG_MAX - (cstr[i] - '0'))/10) return -3; 
     else tmp_slli = tmp_slli * 10 + (cstr[i] - '0'); 
    } 
    else return i+1; 
} 

if(cstr[0] == '-') *slli = tmp_slli*-1; 
else *slli = tmp_slli; 

return 0; 
} 
+0

«Я знаю, что уже есть функции, которые делают это» -> Считаете ли вы использование этих функций для справки? Быстрее писать 'strtof (" .99999999 ", ...)', чем задавать вопрос о StackOverflow. –

ответ

2

Наибольшее представимое float значение меньше 1 возвращается nexttowardf(1, -INFINITY).

Это, как правило, имеет фракцию, отличную от фракции, чем, например, наибольшее представляемое значение float менее 2, которое равно nexttowardf(2, -INFINITY). Это связано с тем, что числа разных величин обычно имеют разное количество бит, доступных для части дроби (поскольку некоторые из битов используются для целочисленной части). Большие числа имеют нулевые биты для части дроби.

Когда float является IEEE-754 32-разрядное двоичное значение с плавающей точкой, который является общим в современных реализациях, самый большой float ниже 1 является 0,999999940395355224609375. Когда подпрограммы, которые преобразуют десятичные цифры в float, являются хорошим качеством, а режим округления является ближайшим (общее значение по умолчанию), то точка, в которой числа переключаются с округления до 0.999999940395355224609375, округляется до 1 на полпути между этими двумя значениями (и точным средняя точка будет округлена до 1).

Сложное преобразование десятичных цифр в двоичную с плавающей запятой. Это решенная проблема, и есть научные статьи об этом, но вы должны в основном полагаться на существующий библиотечный код, если он правильно выполняет работу. Правильное выполнение этого требует значительных затрат времени.

1

Вопрос, который я задаю, заключается в том, как вычислить максимальную долю, которую может выражать float. Как я, из-за отсутствия лучшего термина, знаю, когда поплавок вот-вот переполнится?

Вы ищете:

#include <math.h> 
… nextafterf(1.0f, 0.0f) … 

Но вы должны ознакомиться с гексадецималами C99 для поплавков, а затем вы можете написать константу непосредственно: 0x1.fffffep-1.

+0

Или '0x.ffffffp0' –

Смежные вопросы