Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect number of distinct operators in Halstead metric #161

Open
rdbliss opened this issue Nov 27, 2018 · 4 comments
Open

Incorrect number of distinct operators in Halstead metric #161

rdbliss opened this issue Nov 27, 2018 · 4 comments

Comments

@rdbliss
Copy link
Contributor

rdbliss commented Nov 27, 2018

While trying to fix #160, I noticed that the Halstead visitor counts operands incorrectly. Essentially, it states that every expression that an operator is applied to is a distinct operator. For example, in the current master,

def f(x):
    x + x + x

has two distinct operands. These are x and x + x.

The problem is that the operator visitors claim to know what operands they are being applied to. In x + (x + x), the first + claims to apply to x and (x + x), and treats (x + x) as an actual operand. I believe that Halstead only ever meant variables as operands, not arbitrary expressions containing them.

I believe that this can be fixed by forcing every visitor method to ignore operands entirely and implementing a visit_Name method. I tried this in a quick experiment, and it fixes the above example. It also gives more reasonable results when combined with the visit_Assignment method requested in #160.

@rubik
Copy link
Owner

rubik commented Jan 26, 2019

Hi @rwbogl, I'm very sorry for the long delay. Do you happen to still have the code for this? I have been fixing a lot of issues and I'd like to close these two as well. You are welcome to open a PR!

@eloifavero
Copy link

https://www.geeksforgeeks.org/software-engineering-halsteads-software-metrics/

from Software Engineering | Halstead’s Software Metrics
....
Counting rules for C language –
...

  1. Comments are not considered.
  2. The identifier and function declarations are not considered
  3. All the variables and constants are considered operands.
  4. Global variables used in different modules of the same program are counted as multiple occurrences of the same variable.
  5. Local variables with the same name in different functions are counted as unique operands.
  6. Functions calls are considered as operators.
  7. All looping statements e.g., do {…} while ( ), while ( ) {…}, for ( ) {…}, all control statements e.g., if ( ) {…}, if ( ) {…} else {…}, etc. are considered as operators.
  8. In control construct switch ( ) {case:…}, switch as well as all the case statements are considered as operators.
  9. The reserve words like return, default, continue, break, sizeof, etc., are considered as operators.
  10. All the brackets, commas, and terminators are considered as operators.
  11. GOTO is counted as an operator and the label is counted as an operand.
  12. The unary and binary occurrence of “+” and “-” are dealt separately. Similarly “*” (multiplication operator) are dealt separately.
  13. In the array variables such as “array-name [index]” “array-name” and “index” are considered as operands and [ ] is considered as operator.
  14. In the structure variables such as “struct-name, member-name” or “struct-name -> member-name”, struct-name, member-name are taken as operands and ‘.’, ‘->’ are taken as operators. Some names of member elements in different structure variables are counted as unique operands.
  15. All the hash directive are ignored.

int sort (int x[ ], int n)

{
int i, j, save, im1;
/This function sorts array x in ascending order /
If (n< 2) return 1;
for (i=2; i< =n; i++)
{
im1=i-1;
for (j=1; j< =im1; j++)
if (x[i] < x[j])
{
Save = x[i];
x[i] = x[j];
x[j] = save;
}
}
return 0;
}
Therefore,
N = 91
n = 24
V = 417.23 bits
N^ = 86.51
n2
= 3 (x:array holding integer
to be sorted. This is used both
as input and output)
V
= 11.6
L = 0.027
D = 37.03
L^ = 0.038
T = 610 seconds

def sort(X,n):
if n<2: return 1
for i in range(0,n):
im=i
for j in range(im,n):
print(i,j)
if X[i]>X[j]:
print('troca',X)
X[i],X[j]=X[j],X[i]
return 0
V=[3,7,1,3,5,7,2];sort(V,len(V));print(V);exit(1)
(True, {'loc': 12, 'lloc': 15, 'sloc': 11, 'h1': 2, 'h2': 4, 'N1': 2, 'N2': 4, 'vocab': 6, 'len': 6, 'calc_len': 10.0, 'vol': 15.51, 'diffic': 1.0, 'effort': 15.51, 'time': 0.86})

Comparing the halstead´s numbers of C and Python codes for the same function the differences are very discrepant, they deserve a review. grateful for the attention.

@rubik
Copy link
Owner

rubik commented May 17, 2021

@eloifavero The code above is quite difficult to read. Also, I am not sure those two implementations can be compared because they are quite a lot different. If you post them with proper indentation and syntax highlighting I'll be happy to take a look.

@mwchase
Copy link

mwchase commented May 11, 2022

I'm curious about that, so I'm going to take the code from the source and try touching it up myself.

int sort (int x[ ], int n)

{
    int i, j, save, im1;
    /*This function sorts array x in ascending order */
    If (n< 2) return 1;
    for (i=2; i< =n; i++)
    {
        im1=i-1;
        for (j=1; j< =im1; j++)
            if (x[i] < x[j])
            {
                Save = x[i];
                x[i] = x[j];
                x[j] = save;
            }
    }
    return 0;
}
def sort_translated(x, n):
    if n < 2:
        return 1
    for i in range(2, n + 1):
        im1 = i - 1
        for j in range(1, im1 + 1):
            if x[i] < x[j]:
                save = x[i]
                x[i] = x[j]
                x[j] = save
    return 0


def sort_more_idiomatic(x, n):
    if n < 2:
        return 1
    for i in range(2, n + 1):
        for j in range(1, i):
            if x[i] < x[j]:
                x[i], x[j] = x[j], x[i]
    return 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants