Вычитание поплавков на языке Си - PullRequest
0 голосов
/ 02 сентября 2018
#include <stdio.h>
#include <stdlib.h>

float sum  (float *A, int len) // sum of table of floats
{
    float ss = 0.0;
    int i;

    for(i=0; i < len; ++i)
        ss +=A[i];
    return ss;
}
void print(float A[][3], int row) //// procedure that prints sum of elements for each row in 2D table
{
    int i, j;
    float k;

    for(i = 0; i < row; i++)
    {
        k=0.0;
        for(j = 0; j < 3; j++)
        {
            k=A[i][j]+k;
        }
        printf (" %2.2f  \n",  k);
    }
    return;
}
int compare(const void *p,const void *q) // sort 2D table in ascending order by sum in rows

{
    float *a = (float*)p;
    float *b = (float*)q;
    float l=sum(a,3);
    float r=sum(b,3);         // CORRECTLY WRITTEN COMPARE FUNCTION
    if (l<r) return -1;
    if (l==r) return 0;
    else return 1;
}

/* int compare(const void *p,const void *q)
{
    float *a = (float*)p;
    float *b = (float*)q;
    float l=sum(a,3);
    float r=sum(b,3);          // WRONGLY WRITTEN COMPARE FUNCTION
    return l-r;
} */

int main()
{
    float TAB_1[ ][3]= {{1.3,2.4,1.1},{4.9,5.9,0.},{5.1,5.1, 1.1},{6.1,7.0,0.3},{1.3,1.3, 3.1},
    {1.3,1.3, 0.1},{4.4,4.3, 4.1},{1.3,1.2, 3.1},{1.3,1.3, 8.1}};

    print(TAB_1,sizeof(TAB_1)/sizeof(TAB_1[0]) );
    qsort(TAB_1,sizeof(TAB_1)/sizeof(TAB_1[0]),sizeof(TAB_1[0]),compare);
    puts("");
    print(TAB_1, sizeof(TAB_1)/sizeof(TAB_1[0]));
    return 0;
}

Почему прокомментированная функция, которую я пометил как НЕПРАВИЛЬНО ЗАПИСАННАЯ СРАВНИТЕЛЬНАЯ ФУНКЦИЯ, дает неверный вывод? Это проблема с представлением с плавающей точкой в ​​C или с вычитанием 2 с плавающей точкой? Может кто-нибудь объяснить?

Ответы [ 2 ]

0 голосов
/ 02 сентября 2018

Функция сравнения с l-r неверна, если разница между этими двумя числами меньше 1, точнее, если abs(l-r) < 1. Причина в том, что результат операции с плавающей запятой l-r преобразуется в int, и все, что находится между 0..0.99999.., даст 0, как если бы эти два числа были равны (даже если они не равны).

Следующая короткая программа иллюстрирует это:

int main() {

    float f1 = 3.4;
    float f2 = 3.7;

    int compareResultWrong = f2 - f1;
    int compareResultOK = (f1 < f2);

    printf("result should be 1; Wrong: %d, OK: %d\n", compareResultWrong, compareResultOK);
}
0 голосов
/ 02 сентября 2018

Это проблема с представлением с плавающей точкой в ​​C или с плавающей точкой вычитания 2?

Ни первое, ни второе - это определенно неправильная реализация.

Посмотрите, что происходит, когда -0.01 или 0.01 результат преобразуется в int результат функции?

...