Format reals better

This commit is contained in:
Jeremy Rand 2013-07-24 12:01:38 -05:00
parent 5e7006a3cc
commit d8d4bc60d4
5 changed files with 150 additions and 7 deletions

View File

@ -8,7 +8,10 @@ abCalcExprReal.o: abCalcExpr.h abCalcExprReal.h
abCalcStack.o: abCalcExpr.h abCalcStack.h
abCalcMode.o: abCalcMode.h abCalcExpr.h
abCalcExprInt.o: abCalcExpr.h abCalcMode.h abCalcExprInt.h
abCalc.o: abCalcExpr.h abCalcMode.h abCalcExprReal.h abCalcExprInt.h abCalcStack.h
abCalc.o: abCalc.h abCalcExpr.h abCalcMode.h abCalcExprReal.h abCalcExprInt.h abCalcStack.h
abCalcMain.o: abCalc.h abCalcStack.h abCalcExpr.h
CFLAGS=-g
$(NAME): $(OBJS)
cc -o $(NAME) $(OBJS)

View File

@ -4,6 +4,7 @@
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@ -101,6 +102,17 @@ abCalcExpr *abCalcExprRealParse(abCalcExpr *expr, char *buffer)
char *abCalcExprRealFormat(abCalcExpr *expr, char *buffer)
{
abCalcRealType exp;
abCalcRealType value;
char format[16];
int numDecDigits;
int periodPos = -1;
int zerosStart = -1;
int spaceStart = -1;
int expPos = -1;
int len;
int i;
if (expr == NULL)
return NULL;
@ -110,6 +122,86 @@ char *abCalcExprRealFormat(abCalcExpr *expr, char *buffer)
if (expr->type != abCalcExprTypeReal)
return NULL;
sprintf(buffer, "%f", expr->u.real);
value = expr->u.real;
if (value == 0.0) {
exp = 0.0;
} else {
exp = floor(log10(fabs(value)));
}
if (exp >= 0)
exp++;
if ((exp > 12) ||
(exp < -12)) {
strcpy(format, "%-25.11E");
} else if (exp <= -2) {
double shiftedValue = value * 1.0e12;
if (shiftedValue == floor(shiftedValue)) {
strcpy(format, "%-18.12f");
} else {
strcpy(format, "%-25.11E");
}
} else {
int numDecDigits = (int)(12 - exp);
if (numDecDigits > 12) {
numDecDigits = 12;
}
sprintf(format, "%%-28.%df", numDecDigits);
}
sprintf(buffer, format, value);
len = strlen(buffer);
for (i = 0; i < len; i++) {
switch (buffer[i]) {
case '.':
periodPos = i;
break;
case '0':
if (expPos != -1) {
break;
}
if ((periodPos != -1) &&
(zerosStart == -1)) {
if (periodPos == i - 1) {
zerosStart = periodPos;
} else {
zerosStart = i;
}
}
break;
case 'E':
expPos = i;
break;
case ' ':
spaceStart = i;
break;
default:
if (expPos == -1)
zerosStart = -1;
break;
}
if (spaceStart != -1)
break;
}
if (spaceStart != -1) {
buffer[spaceStart] = '\0';
len = spaceStart;
}
if (zerosStart != -1) {
if (expPos != -1) {
memmove(&buffer[zerosStart], &buffer[expPos], len - expPos + 1);
len = expPos - zerosStart;
}
else {
buffer[zerosStart] = '\0';
}
}
return buffer;
}

View File

@ -1,9 +1,58 @@
/*
abCalcMain.c
By: Jeremy Rand
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "abCalc.h"
#include "abCalcExpr.h"
#include "abCalcStack.h"
char gBuffer[AB_CALC_EXPR_STRING_MAX];
abCalcExpr gExpr;
int main(void)
{
printf("Hello, world!\n");
int timeToQuit = 0;
int depth;
int item;
int len;
abCalcInit();
while (!timeToQuit) {
printf("Stack:\n");
depth = abCalcStackNumItems();
if (depth == 0) {
printf(" Empty!\n");
} else {
for(item = depth - 1; item >= 0; item--) {
abCalcFormatExpr(abCalcStackExprAt(item), gBuffer);
printf(" %3d: %s\n", item + 1, gBuffer);
}
}
timeToQuit = 1;
if (fgets(gBuffer, sizeof(gBuffer), stdin) != NULL) {
len = strlen(gBuffer);
if ((gBuffer[len - 1] == '\r') ||
(gBuffer[len - 1] == '\n')) {
gBuffer[len - 1] = '\0';
}
if ((abCalcParseExpr(&gExpr, gBuffer) != NULL) &&
(abCalcStackExprPush(&gExpr) != NULL)) {
timeToQuit = 0;
}
}
}
exit(0);
}

View File

@ -54,11 +54,10 @@ int abCalcStackNumItems(void)
}
abCalcExpr *abCalcStackExprAt(abCalcExpr *expr, int depth)
abCalcExpr *abCalcStackExprAt(int depth)
{
abCalcExpr *result = NULL;
if ((depth < gStackNumItems) &&
(expr != NULL)) {
if (depth < gStackNumItems) {
result = &(gStack[gStackNumItems - 1 - depth]);
}

View File

@ -16,7 +16,7 @@ abCalcExpr *abCalcStackExprPush(abCalcExpr *expr);
abCalcExpr *abCalcStackExprPop(abCalcExpr *expr);
abCalcExpr *abCalcStackExprAt(abCalcExpr *expr, int depth);
abCalcExpr *abCalcStackExprAt(int depth);
int abCalcStackNumItems(void);