Add limited support for units that are related by affine rather
than linear relations. We can now convert degC to degF. 586 units, 56 prefixes You have: 24 degC You want: degF 75.2 You have: degC You want: K (-> x*1 +273.15) (<- y*1 -273.15)
This commit is contained in:
parent
f70f5c2077
commit
9c95bc1c1c
@ -53,6 +53,8 @@ struct unittype {
|
||||
char *numerator[MAXSUBUNITS];
|
||||
char *denominator[MAXSUBUNITS];
|
||||
double factor;
|
||||
double offset;
|
||||
int quantity;
|
||||
};
|
||||
|
||||
struct {
|
||||
@ -78,7 +80,7 @@ void initializeunit(struct unittype * theunit);
|
||||
int addsubunit(char *product[], char *toadd);
|
||||
void showunit(struct unittype * theunit);
|
||||
void zeroerror(void);
|
||||
int addunit(struct unittype * theunit, char *toadd, int flip);
|
||||
int addunit(struct unittype *theunit, char *toadd, int flip, int quantity);
|
||||
int compare(const void *item1, const void *item2);
|
||||
void sortunit(struct unittype * theunit);
|
||||
void cancelunit(struct unittype * theunit);
|
||||
@ -207,8 +209,10 @@ readunits(const char *userfile)
|
||||
void
|
||||
initializeunit(struct unittype * theunit)
|
||||
{
|
||||
theunit->factor = 1.0;
|
||||
theunit->numerator[0] = theunit->denominator[0] = NULL;
|
||||
theunit->factor = 1.0;
|
||||
theunit->offset = 0.0;
|
||||
theunit->quantity = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -237,6 +241,8 @@ showunit(struct unittype * theunit)
|
||||
int counter = 1;
|
||||
|
||||
printf("\t%.8g", theunit->factor);
|
||||
if (theunit->offset)
|
||||
printf("&%.8g", theunit->offset);
|
||||
for (ptr = theunit->numerator; *ptr; ptr++) {
|
||||
if (ptr > theunit->numerator && **ptr &&
|
||||
!strcmp(*ptr, *(ptr - 1)))
|
||||
@ -284,16 +290,17 @@ zeroerror(void)
|
||||
/*
|
||||
Adds the specified string to the unit.
|
||||
Flip is 0 for adding normally, 1 for adding reciprocal.
|
||||
Quantity is 1 if this is a quantity to be converted rather than a pure unit.
|
||||
|
||||
Returns 0 for successful addition, nonzero on error.
|
||||
*/
|
||||
|
||||
int
|
||||
addunit(struct unittype * theunit, char *toadd, int flip)
|
||||
addunit(struct unittype * theunit, char *toadd, int flip, int quantity)
|
||||
{
|
||||
char *scratch, *savescr;
|
||||
char *item;
|
||||
char *divider, *slash;
|
||||
char *divider, *slash, *offset;
|
||||
int doingtop;
|
||||
|
||||
if (!strlen(toadd))
|
||||
@ -313,7 +320,17 @@ addunit(struct unittype * theunit, char *toadd, int flip)
|
||||
item = strtok(scratch, " *\t\n/");
|
||||
while (item) {
|
||||
if (strchr("0123456789.", *item)) { /* item is a number */
|
||||
double num;
|
||||
double num, offsetnum;
|
||||
|
||||
if (quantity)
|
||||
theunit->quantity = 1;
|
||||
|
||||
offset = strchr(item, '&');
|
||||
if (offset) {
|
||||
*offset = 0;
|
||||
offsetnum = atof(offset+1);
|
||||
} else
|
||||
offsetnum = 0.0;
|
||||
|
||||
divider = strchr(item, '|');
|
||||
if (divider) {
|
||||
@ -323,19 +340,25 @@ addunit(struct unittype * theunit, char *toadd, int flip)
|
||||
zeroerror();
|
||||
return 1;
|
||||
}
|
||||
if (doingtop ^ flip)
|
||||
if (doingtop ^ flip) {
|
||||
theunit->factor *= num;
|
||||
else
|
||||
theunit->offset *= num;
|
||||
} else {
|
||||
theunit->factor /= num;
|
||||
theunit->offset /= num;
|
||||
}
|
||||
num = atof(divider + 1);
|
||||
if (!num) {
|
||||
zeroerror();
|
||||
return 1;
|
||||
}
|
||||
if (doingtop ^ flip)
|
||||
if (doingtop ^ flip) {
|
||||
theunit->factor /= num;
|
||||
else
|
||||
theunit->offset /= num;
|
||||
} else {
|
||||
theunit->factor *= num;
|
||||
theunit->offset *= num;
|
||||
}
|
||||
}
|
||||
else {
|
||||
num = atof(item);
|
||||
@ -343,12 +366,16 @@ addunit(struct unittype * theunit, char *toadd, int flip)
|
||||
zeroerror();
|
||||
return 1;
|
||||
}
|
||||
if (doingtop ^ flip)
|
||||
if (doingtop ^ flip) {
|
||||
theunit->factor *= num;
|
||||
else
|
||||
theunit->offset *= num;
|
||||
} else {
|
||||
theunit->factor /= num;
|
||||
|
||||
theunit->offset /= num;
|
||||
}
|
||||
}
|
||||
if (doingtop ^ flip)
|
||||
theunit->offset += offsetnum;
|
||||
}
|
||||
else { /* item is not a number */
|
||||
int repeat = 1;
|
||||
@ -534,7 +561,7 @@ reduceproduct(struct unittype * theunit, int flip)
|
||||
free(*product);
|
||||
*product = NULLUNIT;
|
||||
}
|
||||
if (addunit(theunit, toadd, flip))
|
||||
if (addunit(theunit, toadd, flip, 0))
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
@ -613,6 +640,20 @@ showanswer(struct unittype * have, struct unittype * want)
|
||||
showunit(have);
|
||||
showunit(want);
|
||||
}
|
||||
else if (have->offset != want->offset) {
|
||||
if (want->quantity)
|
||||
printf("WARNING: conversion of non-proportional quantities.\n");
|
||||
printf("\t");
|
||||
if (have->quantity)
|
||||
printf("%.8g\n",
|
||||
(have->factor + have->offset-want->offset)/want->factor);
|
||||
else
|
||||
printf(" (-> x*%.8g %+.8g)\n\t (<- y*%.8g %+.8g)\n",
|
||||
have->factor / want->factor,
|
||||
(have->offset-want->offset)/want->factor,
|
||||
want->factor / have->factor,
|
||||
(want->offset - have->offset)/have->factor);
|
||||
}
|
||||
else
|
||||
printf("\t* %.8g\n\t/ %.8g\n", have->factor / want->factor,
|
||||
want->factor / have->factor);
|
||||
@ -666,10 +707,10 @@ main(int argc, char **argv)
|
||||
strlcpy(havestr, argv[optind], sizeof(havestr));
|
||||
strlcpy(wantstr, argv[optind + 1], sizeof(wantstr));
|
||||
initializeunit(&have);
|
||||
addunit(&have, havestr, 0);
|
||||
addunit(&have, havestr, 0, 1);
|
||||
completereduce(&have);
|
||||
initializeunit(&want);
|
||||
addunit(&want, wantstr, 0);
|
||||
addunit(&want, wantstr, 0, 1);
|
||||
completereduce(&want);
|
||||
showanswer(&have, &want);
|
||||
}
|
||||
@ -687,7 +728,7 @@ main(int argc, char **argv)
|
||||
putchar('\n');
|
||||
exit(0);
|
||||
}
|
||||
} while (addunit(&have, havestr, 0) ||
|
||||
} while (addunit(&have, havestr, 0, 1) ||
|
||||
completereduce(&have));
|
||||
do {
|
||||
initializeunit(&want);
|
||||
@ -698,7 +739,7 @@ main(int argc, char **argv)
|
||||
putchar('\n');
|
||||
exit(0);
|
||||
}
|
||||
} while (addunit(&want, wantstr, 0) ||
|
||||
} while (addunit(&want, wantstr, 0, 1) ||
|
||||
completereduce(&want));
|
||||
showanswer(&have, &want);
|
||||
}
|
||||
|
@ -671,14 +671,14 @@ Xunit 1.00206e-13 m
|
||||
k 1.38047e-16 erg/degC
|
||||
|
||||
|
||||
degC K
|
||||
degC 1&+273.15 K
|
||||
kelvin K
|
||||
brewster 1e-12 m2/newton
|
||||
degF 5|9 degC
|
||||
degreesrankine degF
|
||||
degF 5|9&255.37222222222222222222 K
|
||||
degreesrankine 5|9 K
|
||||
degrankine degreesrankine
|
||||
degreerankine degF
|
||||
degreaumur 10|8 degC
|
||||
degreerankine degreesrankine
|
||||
degreaumur 10|8&+273.15 K
|
||||
drachm 60 grain
|
||||
poncelet 100 kg m g / sec
|
||||
denier .05|450 gram / m
|
||||
|
Loading…
Reference in New Issue
Block a user