+
+/*
+ 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 */
+}
+