Trying to understand MRTG

D

dolbz.cardiff

Hi,

I would have asked this in the MRTG newsgroups but they all appear to
be dead. Sorry if this is the wrong place for the question.

I have been looking at the MRTG
(http://people.ee.ethz.ch/~oetiker/webtools/mrtg/) source code in order
to gain an understanding of how it works. Everything was going fine
until I ran into the 'diff' function. Could anyone provide a brief
overview of what it is actually doing. I am fairly new to C so cant
really follow what's going on with the pointers everywhere. The a and b
variables are char arrays containing just numbers/digits.

Here it is...

static double diff(a,b)
char *a,*b;
{
char res[MAXL], *a1, *b1, *r1;
int c,x,m;
if (*a == '-' && *b == '-') {
b1 = b + 1;
b = a + 1;
a = b1;
}

while (!isdigit((int)*a))
a++;
while (!isdigit((int)*b))
b++;
a1 = &a[strlen(a)-1];
m = max(strlen(a),strlen(b));
r1 = &res[m+1];
for (b1 = res;b1 <= r1; b1++) *b1 = ' ';
b1 = &b[strlen(b)-1];
r1[1] = 0; /* Null terminate result */
c = 0;
for (x=0; x<m; x++) {
if (a1 >= a && b1 >= b) {
*r1 = ((*a1 - c) - *b1) + '0';
} else if (a1 >= a) {
*r1 = (*a1 - c);
} else {
*r1 = ('0' - *b1 - c) + '0';
}
if (*r1 < '0') {
*r1 += 10;
c=1;
} else {
c=0;
}
a1--;b1--;r1--;
}
if (c) {
r1 = &res[m+1];
for (x=0; isdigit((int)*r1) && x<m; x++,r1--) {
*r1 = ('9' - *r1 + c) + '0';
if (*r1 > '9') {
*r1 -= 10;
c=1;
} else {
c=0;
}
}
return(-atof(res));
} else
return(atof(res));
}

Thanks in advance
Dolbz
 
A

Anonymous 7843

I have been looking at the MRTG
(http://people.ee.ethz.ch/~oetiker/webtools/mrtg/) source code in order
to gain an understanding of how it works. Everything was going fine
until I ran into the 'diff' function. Could anyone provide a brief
overview of what it is actually doing. I am fairly new to C so cant
really follow what's going on with the pointers everywhere. The a and b
variables are char arrays containing just numbers/digits.
[see referenced article for code]

You only want to know what it's doing? It's taking two character
strings, treating them as numbers and computing the arithmetic
difference (minus operation) between them. I can't vouch for
its accuracy, but it appears to be doing it in a way that would
work when the numbers are very large (beyond the range of a long)
or very precise (beyond the range of a double holding an integer).
 
S

Simon Biber

Hi,

I would have asked this in the MRTG newsgroups but they all appear to
be dead. Sorry if this is the wrong place for the question.

I have been looking at the MRTG
(http://people.ee.ethz.ch/~oetiker/webtools/mrtg/) source code in order
to gain an understanding of how it works. Everything was going fine
until I ran into the 'diff' function. Could anyone provide a brief
overview of what it is actually doing. I am fairly new to C so cant
really follow what's going on with the pointers everywhere. The a and b
variables are char arrays containing just numbers/digits.

Here it is... [...]
Thanks in advance
Dolbz

Try putting it into a program of its own...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXL 1024
#define max(d1,d2) ((d1)>(d2)?(d1):(d2))

static double diff(a,b)
char *a,*b;
{
char res[MAXL], *a1, *b1, *r1;
int c,x,m;
if (*a == '-' && *b == '-') {
b1 = b + 1;
b = a + 1;
a = b1;
}

while (!isdigit((int)*a))
a++;
while (!isdigit((int)*b))
b++;
a1 = &a[strlen(a)-1];
m = max(strlen(a),strlen(b));
r1 = &res[m+1];
for (b1 = res;b1 <= r1; b1++) *b1 = ' ';
b1 = &b[strlen(b)-1];
r1[1] = 0; /* Null terminate result */
c = 0;
for (x=0; x<m; x++) {
if (a1 >= a && b1 >= b) {
*r1 = ((*a1 - c) - *b1) + '0';
} else if (a1 >= a) {
*r1 = (*a1 - c);
} else {
*r1 = ('0' - *b1 - c) + '0';
}
if (*r1 < '0') {
*r1 += 10;
c=1;
} else {
c=0;
}
a1--;b1--;r1--;
}
if (c) {
r1 = &res[m+1];
for (x=0; isdigit((int)*r1) && x<m; x++,r1--) {
*r1 = ('9' - *r1 + c) + '0';
if (*r1 > '9') {
*r1 -= 10;
c=1;
} else {
c=0;
}
}
return(-atof(res));
} else
return(atof(res));
}

int main(void)
{
char a[] = "7083549724304467820544",
b[] = "4722366482869645213696";
size_t m = max(strlen(a), strlen(b));
printf("a = %*s\n"
"b = %*s\n"
"diff(a, b) = %*.0f\n", m, a, m, b, m, diff(a, b));
return 0;
}

Now you get the result:
a = 7083549724304467820544
b = 4722366482869645213696
diff(a, b) = 2361183241434822606848

It calculates the difference between two integers in strings
digit-by-digit, putting the result into a string variable. It then
converts that string to a floating-point representation in a double.

It seems to work with integers far greater than would fit in a "long" or
"long long". In fact, the result size is limited to MAXL - 1 decimal
digits. The size is also be limited by what can be converted to a
double, which means around 308 digits on my implementation, but the
precision of a double may only be accurate to around 15 digits.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top