0

I have this code in python and it works correctly. The idea of this code is compute the repetition of each value in the array depending on the threshold value. The output for the python code is [value,repetition]

[1.2, 3, 2.4, 1, 2.5, 1, 2.3, 1, 2.4, 1, 8.5, 2, 8.9, 1, 9.11, 1]
def dif(x, y, ma1):
    res=0
    if(math.fabs(x-y) <= ma1):
        res=1
    return res

def enc(text,th):
    coded=[]
    coded.clear()
    index=0
    unt=1
    while index<=(len(text)-1):  
      if index==(len(text)-1) or  dif(text[index],text[(index+1)],th) !=1:  
        coded.append(text[index])
        coded.append(unt)       
        unt=1
      else:
        unt=unt+1            
      index=index+1   
    return coded
SenList=[1.1,1.1,1.2,2.4,2.5,2.3,2.4,8.6,8.5,8.9,9.11]
th = 0.1
comm= enc(SenList,th)
print(comm)

And this is the C code and the output for the C cod is :

1.100000  2  1.200000 1  2.500000  2  2.300000  1  2.400000  1  
8.600000  1 8.500000  1  8.900000  1  9.110000  1
int dif(float x,float y,float sigma1){
    int res=0;
    if(fabsf(x-y) <= sigma1)
        res=1; 
    return res;
}

void RL(){

    float text [] = {1.1,1.1,1.2,2.4,2.5,2.3,2.4,8.6,8.5,8.9,9.11} ;           
    int n = sizeof(text)/sizeof(text[0]); 
    float th =0.1;    
    float num[30]; int nc = 0;
    int cou[30];   int nc1= 0;
    int index=0;
    int unt=1;
    while (index<(n)){  
      if ( (index==(n-1)) || (dif(text[index],text[index+1],th)!=1)  )  {
                   
            cou[nc]  = unt; nc=nc+1;
            num[nc1]  = text[index]; nc1=nc1+1;
            unt=1;
      }
      else{
        unt=unt+1;            
      }
        index=index+1  ;
 
    }
    for(int i=0; i<nc;i++){ 
       printf(" %3f   %d \n ",num[i],cou[i]);
           
        }   
}

Why the C code deal with the values as int not float(compute the repetition as int)? how can fix the problem in this code please? Note: the C code work correctly if I use int array.

Barmar
  • 741,623
  • 53
  • 500
  • 612
lena
  • 730
  • 2
  • 11
  • 23
  • 2
    `abs` is integer absolute value. Use `fabsf` instead. – user3386109 Jul 12 '23 at 22:29
  • I used it but the output is still not the same with python code. – lena Jul 12 '23 at 22:38
  • Then I think you need to [edit] the question, with your new code, and new results. You do have numbers that differ by exactly the threshold, so rounding errors can give different results. You could change all of the `float` to `double`, and use `fabs`. That may change the results. – user3386109 Jul 12 '23 at 22:39
  • What precision is a python number compared to a C float? – tinman Jul 12 '23 at 22:40
  • @user3386109, I used fabsf and I update the output of C code – lena Jul 12 '23 at 22:47
  • Your `dif` functions seem to be over-complicated. In Python: `return 1 if math.fabs(x-y) <= ma1 else 0`, but really it should be returning either true or false. – Chris Jul 12 '23 at 22:51
  • If you use `float` variables, the exact value of 1.1 is 1.10000002384185791015625, the exact value of 1.2 is 1.2000000476837158203125, the exact value of 0.1 is 0.100000001490116119384765625, and the exact value of the absolute difference between 1.1 and 1.2 is 0.10000002384185791015625. So `fabsf(x-y)` is not less than or equal to `sigma1`. If you switch from `float` to `double` and use `fabs`, you'll get different results. For more information, see [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – user3386109 Jul 12 '23 at 23:11
  • 1
    @user3386109 my bad. you are right. float uses 32 bit – Onyambu Jul 13 '23 at 00:48
  • A Python `float` is equivalent to a C `double`. – Mark Ransom Jul 13 '23 at 01:05
  • AFAICS, your Python sample data `[1.1,1.1,1.2,2.4,2.5,2.3,2.4,8.6,8.5,8.9,9.11]` has 2 entries with `1.1` and 1 with `1.2`, yet you claim the output is/should be `[1.2, 3, …]` (3 entries with `1.2`). These don't match in my brain. – Jonathan Leffler Jul 13 '23 at 02:22

1 Answers1

0

From the comment by @user3386109 we should consider the difference between the float and double in both the Python and C codes. A way to do it is by adding a small Epsilon that should compensate on the fact the (1.2-1.1) is not exactly 0.1 For the example I'll use Epsilon of 10e-6 (you may use even smaller number).

Here is the modified Python code:

import math
EPS = 0.000001

def dif(x, y, ma1):
    res=0
    z = math.fabs(x-y) 
    if( z <= (ma1+EPS)):
        res=1
    return res

def enc(text,th):
    coded=[]
    coded.clear()
    index=0
    unt=1
    while index<=(len(text)-1):  
      if index==(len(text)-1) or  dif(text[index],text[(index+1)],th) !=1:  
        coded.append(text[index])
        coded.append(unt)       
        unt=1
      else:
        unt=unt+1            
      index=index+1   
    return coded
SenList=[1.1,1.1,1.2,2.4,2.5,2.3,2.4,8.6,8.5,8.9,9.11]
th = 0.1
comm= enc(SenList,th)
print(comm)

The result of this run is different from the original code:

[1.2, 3, 2.5, 2, 2.4, 2, 8.5, 2, 8.9, 1, 9.11, 1]

Here is the modified C code:

#include <stdio.h>
#include <math.h>

#define EPS 10.0e-6
int dif(float x,float y,float sigma1){
    int res=0;
    float z;
    
    z = fabs(x-y);
    if(z <= (sigma1+EPS))
        res=1; 
    return res;
}
void RL(){

    float text [] = {1.1,1.1,1.2,2.4,2.5,2.3,2.4,8.6,8.5,8.9,9.11} ;           
    int n = sizeof(text)/sizeof(text[0]); 
    float th =0.1;    
    float num[30]; int nc = 0;
    int cou[30];   int nc1= 0;
    int index=0;
    int unt=1;
    while (index<(n)){  
      if ( (index==(n-1)) || (dif(text[index],text[index+1],th)!=1)  )  {
                   
            cou[nc]  = unt; nc=nc+1;
            num[nc1]  = text[index]; nc1=nc1+1;
            unt=1;
      }
      else{
        unt=unt+1;            
      }
        index=index+1  ;
 
    }
    for(int i=0; i<nc;i++){ 
       printf("%3.2f, %d, ",num[i],cou[i]);
           
        }   
}

int main()
{
    printf("C code output: ");
    RL();

    return 0;
}

The result for the C code is the same as Python after the change:

C code output: 1.20, 3, 2.50, 2, 2.40, 2, 8.50, 2, 8.90, 1, 9.11, 1,

If you run with debugger both codes, you'll find the the 'z' value inside the dif() function, is different on the 3rd iteration between C and Python:

    in Python z= 0.09999999999999987

    in C      z= 0.100000024

By using the small Epsilon inside the dif() function, you'll get the same results in both languages for this task.

yosi
  • 18
  • 5
  • Python has a built-in function [`math.isclose`](https://docs.python.org/3/library/math.html#math.isclose) for doing a comparison between floats. – Mark Ransom Jul 15 '23 at 18:45