Мне нужно реализовать программу, которая вычисляет машинный эпсилон для float и double.
Я написал эти функции:
int feps(){
//machine epsilon for float
float tmp=1;
int d=0;
while(1+(tmp=tmp/2)>1.0f)d++;
return d;
}
int deps(){
//machine epsilon for double
double tmp=1;
int d=0;
while(1+(tmp=tmp/2)>1.0)d++;
return d;
}
Примечание:
64-битный машинный компилятор gcc 4.9.1 target: x86_64-linux-gnu
32-битный машинный компилятор gcc 4.8.2 target: i686-linux-gnu
Я пробовал это на 64-битной машине и получил следующие результаты:
Float 23
Double 52
Как я и ожидал, затем я попробовал это на 32-битная виртуальная машина, и результаты были очень странными:
Float 63
Double 63
Я также пытался скомпилировать свою программу с помощью -mpc32, - mpc64 и -mpc80, и вот результат:
-mpc32 Float 23, Double 23
-mpc64 Float 52, Double 52
-mpc80 Float 63, Double 63
Я также пробовал этот вариант компиляции на 64-битной машине, но результаты всегда были 23 и 52.
Я знаю это float с одинарной точностью, а double с двойной точностью, но возможно, что компилятор моей 32-битной виртуальной машины использует binary80 как для чисел с плавающей запятой, так и для чисел двойной точности"?
Я совершенно уверен, что мой код правильный, поэтому я думаю, что проблема связана с компилятором или чем-то более тонким.
Я потратил весь день на поиск информации о плавающей запятой и кое-что прочитал о MMX / SSE инструкция, но я мало что понял, и кое-что о FPU x87, которое может создать некоторые проблемы.
Обновление:
Я хочу поблагодарить всех, кто мне помог, мне удалось получить реальное значение эпсилон для float и double на 32-битной виртуальной машине, это код:
int feps(){
float tmp=1;
int d=0;
float tmp2=1;
do{
tmp2=1+(tmp=tmp/2);
d++;
}while(tmp2>1.0f);
return d-1;
}
int deps(){
double tmp=1;
int d=0;
double tmp2=1;
do{
tmp2=1+(tmp=tmp/2);
d++;
}while(tmp2>1.0);
return d-1;
}
как вы можете видеть, нам нужно поместить промежуточный результат в переменную, чтобы мы могли предотвратить оценку 1+ (tmp = tmp / 2) как long double в тесте цикла. < br>
printf("%zu\n",sizeof(float));
. Это не скажет вам, что такое эпсилон, но расскажет, сколько байтов уfloat
на виртуальной машине. - person user3386109   schedule 16.03.2015float
, поэтому я не совсем понимаю, как это будет полное объяснение - person M.M   schedule 16.03.2015FLT_EPSILON
иDBL_EPSILON
, определенные в<float.h>
, на всех этих платформах.float
иdouble
могут быть одного и того же типа. - person chqrlie   schedule 16.03.2015tmp
какvolatile
. Это должно предотвратить кэширование переменной в регистре и избежать проблем с избыточной точностью при вычислениях на FPU x87. - person njuffa   schedule 16.03.2015