detect division by 0
This commit is contained in:
parent
ef298cddd0
commit
20946c44d4
@ -132,7 +132,8 @@ The keys on the original calculator map as follows:
|
||||
Hold `mode` and `0` at the same time to turn off. NOTE: There is no auto power off.
|
||||
|
||||
# Bugs
|
||||
1. The calculator does not properly check for overflow.
|
||||
1. The calculator does not properly check for underflow or overflow.
|
||||
1. After division by 0, it's possible to negate `Error` to get an invalid number.
|
||||
1. There are probably more bugs waiting to be discovered.
|
||||
|
||||
# Internals
|
||||
|
@ -48,7 +48,11 @@ __xdata dec80* get_y(void){
|
||||
}
|
||||
|
||||
static void do_binary_op(void (*f_ptr)(dec80*, const dec80*)){
|
||||
f_ptr(&stack(STACK_Y), &stack(STACK_X));
|
||||
if (decn_is_nan(&stack(STACK_Y)) || decn_is_nan(&stack(STACK_X))){
|
||||
set_dec80_NaN(&stack(STACK_Y));
|
||||
} else {
|
||||
f_ptr(&stack(STACK_Y), &stack(STACK_X));
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|
||||
|
@ -339,15 +339,28 @@ static uint8_t decn_is_zero(const dec80* x){
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t decn_is_nan(const dec80* x){
|
||||
uint8_t i;
|
||||
if (x->exponent != DEC80_NAN_EXP){
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < DEC80_NUM_LSU; i++){
|
||||
if (x->lsu[i] != 0xff){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef EXTRA_CHECKS
|
||||
void set_dec80_NaN(dec80* dest){
|
||||
uint8_t i;
|
||||
|
||||
//set exponent to special val
|
||||
dest->exponent = 0xff;
|
||||
//clear nibbles
|
||||
dest->exponent = DEC80_NAN_EXP;
|
||||
//set all nibbles
|
||||
for (i = 0; i < DEC80_NUM_LSU; i++){
|
||||
dest->lsu[i] = 0;
|
||||
dest->lsu[i] = 0xff;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -713,6 +726,9 @@ void div_decn(dec80* acc, const dec80* x){
|
||||
#ifdef EXTRA_CHECKS
|
||||
if (decn_is_zero(x)){
|
||||
set_dec80_NaN(acc);
|
||||
#ifdef DESKTOP
|
||||
printf("error division by 0\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -775,6 +791,20 @@ int8_t decn_to_str(char* buf, const dec80* x){
|
||||
uint8_t use_sci = 0;
|
||||
static __xdata dec80 tmp;
|
||||
|
||||
//handle corner case of NaN
|
||||
if (decn_is_nan(x)){
|
||||
buf[0] = 'E';
|
||||
buf[1] = 'r';
|
||||
buf[2] = 'r';
|
||||
buf[3] = 'o';
|
||||
buf[4] = 'r';
|
||||
buf[5] = '\0';
|
||||
#ifdef DEBUG
|
||||
printf (" corner case NaN ");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
//copy and normalize
|
||||
copy_decn(&tmp, x);
|
||||
remove_leading_zeros(&tmp);
|
||||
|
@ -19,6 +19,7 @@ extern "C" {
|
||||
//allow full range, but reserve -16384 for special numbers
|
||||
#define DEC80_MIN_EXP (-16383)
|
||||
#define DEC80_MAX_EXP 16383
|
||||
#define DEC80_NAN_EXP (-16383 - 1)
|
||||
|
||||
//decimal80 unpacked into 80 bits
|
||||
// for computation
|
||||
@ -45,6 +46,7 @@ void build_dec80(dec80* dest, const char* signif_str, int16_t exponent);
|
||||
|
||||
void set_dec80_zero(dec80* dest);
|
||||
void set_dec80_NaN(dec80* dest);
|
||||
uint8_t decn_is_nan(const dec80* x);
|
||||
|
||||
void negate_decn(dec80* x);
|
||||
int8_t compare_decn(const dec80* a, const dec80* b); //a<b: -1, a==b: 0, a>b: 1
|
||||
|
Loading…
Reference in New Issue
Block a user