X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=ckclib.c;h=51b9f06dfd79b39d80f69bf60a5aaa8908ff73d1;hb=ac474f1b8a669fcca9757cc53cf48146f08f9828;hp=ac6f62df23e2dbbdf8c6fd9e32c08510ec8f44b9;hpb=411dc6a9768de308b60f383ce5c278b25b740122;p=ckermit.git diff --git a/ckclib.c b/ckclib.c index ac6f62d..51b9f06 100644 --- a/ckclib.c +++ b/ckclib.c @@ -1,4 +1,4 @@ -char * cklibv = "C-Kermit library, 9.0.049, 30 Dec 2010"; +char * cklibv = "C-Kermit library, 9.0.052, 29 Jun 2011"; #define CKCLIB_C @@ -8,7 +8,7 @@ char * cklibv = "C-Kermit library, 9.0.049, 30 Dec 2010"; Author: Frank da Cruz , Columbia University Academic Information Systems, New York City. - Copyright (C) 1999, 2010, + Copyright (C) 1999, 2011, Trustees of Columbia University in the City of New York. All rights reserved. See the C-Kermit COPYING.TXT file or the copyright text in the ckcmai.c module for disclaimer and permissions. @@ -54,6 +54,7 @@ char * cklibv = "C-Kermit library, 9.0.049, 30 Dec 2010"; chknum() - Checks if string is a (possibly signed) integer. rdigits() - Checks if string is composed only of decimal digits. isfloat() - Checks if string is a valid floating-point number. + ckround() - Rounds a floating-point number to desired precision. parnam() - Returns parity name string. hhmmss() - Converts seconds to hh:mm:ss string. lset() - Write fixed-length field left-adjusted into a record. @@ -2051,6 +2052,122 @@ isfloat(s,flag) char *s; int flag; { floatval = f; /* Set result */ return(d ? 2 : 1); /* Succeed */ } + +/* + c k r o u n d -- Rounds a floating point number or an integer. + + fpnum: + Floating-point number to round. + places: + Positive...To how many decimal places. + Zero.......Round to integer. + Negative...-1 = nearest ten, -2 = nearest 100, -3 = nearest thousand, etc. + obuf + Output buffer for string result if desired. + obuflen + Length of output buffer. + Returns: + Result as CKFLOAT (which is not going to be as exact as the string result) + And the exact result in the string output buffer, if one was specified. +*/ +CKFLOAT +#ifdef CK_ANSIC +ckround(CKFLOAT fpnum, int places, char *obuf, int obuflen) +#else +ckround(fpnum,places,obuf,obuflen) + CKFLOAT fpnum; int places, obuflen; char *obuf; +#endif /* CK_ANSIC */ +/* ckround */ { + char *s, *s2, *d; + int i, p, len, x, n, digits; + int carry = 0; + int minus = 0; + char buf[200]; + char * number; + CKFLOAT value; + extern int fp_digits; + + sprintf(buf,"%200.100f",fpnum); /* Make string version to work with */ + number = (char *) buf; /* Make pointer to it */ + + p = places; /* Precision */ + d = (char *)0; /* Pointer to decimal or string end */ + + s = number; /* Fix number... */ + while (*s == ' ' || *s == '\011') s++; /* Strip leading whitespace */ + if (*s == '+') s++; /* Skip leading plus sign*/ + number = s; /* Start of number */ + if (*s == '-') { minus++; number++; s++; } /* Remember if negative */ + + s = number; /* Don't allow false precision */ + n = 0; + while (*s && *s != '.') s++, n++; /* Find decimal */ + + if (p + n > fp_digits) /* Too many digits */ + p = fp_digits - n; /* Don't ask for bogus precision */ + if (p < 0) p = 0; /* But don't ask for less than zero */ + if (n > fp_digits) /* Integer part has too many digits */ + *s = 0; /* but we can't truncate it */ + else /* Magnitude is OK */ + number[fp_digits+1] = 0; /* Truncate fractional part. */ + + len = (int)strlen(number); /* Length of non-bogus number */ + d = s; /* Pointer to decimal point */ + if (p > 0) { /* Rounding the fractional part */ + if (n + p < len) { /* If it's not already shorter */ + if (*s == '.') s++; /* Skip past decimal */ + s += p; /* Go to desired spot */ + if (*s > '4' && *s <= '9') /* Check value of digit */ + carry = 1; + *s = 0; /* And end the string */ + s--; /* Point to last digit */ + } + } else if (p == 0) { /* Rounding to integer */ + if (*s == '.') { + *s = 0; /* erase the decimal point */ + if (*(s+1)) { /* and there is a factional part */ + if (*(s+1) > '4' && *(s+1) <= '9') /* Check for carry */ + carry = 1; + } + s--; /* Point to last digit */ + } + } else { /* Rounding the integer part */ + if (s + p > number) { /* as in "the nearest hundred" */ + s += p; /* Go left to desired digit */ + *d = 0; /* Discard fraction */ + carry = 0; + if (*s > '4') /* Check first digit of fraction */ + carry = 1; /* and set carry flag */ + s2 = s; + while (s2 < d) /* Fill in the rest with zeros */ + *s2++ = '0'; + s--; /* Point to last digit */ + } + } + if (carry) { /* Handle carry, if any */ + while (s >= number) { + if (*s == '.') { /* Skip backwards over decimal */ + s--; + continue; + } + *s += 1; /* Add 1 to current digit */ + carry = 0; + if (*s <= '9') /* If result is 9 or less */ + break; /* we're done */ + *s = '0'; /* Otherwise put 0 */ + carry = 1; /* carry the 1 */ + s--; /* and back up to next digit */ + } + } +#ifdef __alpha + sscanf(number,"%f",&value); /* Convert back to floating point */ +#else + sscanf(number,"%lf",&value); /* Convert back to floating point */ +#endif + if (obuf) strncpy(obuf,number,obuflen); /* Set string result */ + return(value); /* Return floating-point result */ +} + #endif /* CKFLOAT */ /* Sorting routines... */