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.
|
Hold `mode` and `0` at the same time to turn off. NOTE: There is no auto power off.
|
||||||
|
|
||||||
# Bugs
|
# 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.
|
1. There are probably more bugs waiting to be discovered.
|
||||||
|
|
||||||
# Internals
|
# Internals
|
||||||
|
@ -48,7 +48,11 @@ __xdata dec80* get_y(void){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void do_binary_op(void (*f_ptr)(dec80*, const dec80*)){
|
static void do_binary_op(void (*f_ptr)(dec80*, const dec80*)){
|
||||||
|
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));
|
f_ptr(&stack(STACK_Y), &stack(STACK_X));
|
||||||
|
}
|
||||||
pop();
|
pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,15 +339,28 @@ static uint8_t decn_is_zero(const dec80* x){
|
|||||||
return 1;
|
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
|
#ifdef EXTRA_CHECKS
|
||||||
void set_dec80_NaN(dec80* dest){
|
void set_dec80_NaN(dec80* dest){
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
|
||||||
//set exponent to special val
|
//set exponent to special val
|
||||||
dest->exponent = 0xff;
|
dest->exponent = DEC80_NAN_EXP;
|
||||||
//clear nibbles
|
//set all nibbles
|
||||||
for (i = 0; i < DEC80_NUM_LSU; i++){
|
for (i = 0; i < DEC80_NUM_LSU; i++){
|
||||||
dest->lsu[i] = 0;
|
dest->lsu[i] = 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -713,6 +726,9 @@ void div_decn(dec80* acc, const dec80* x){
|
|||||||
#ifdef EXTRA_CHECKS
|
#ifdef EXTRA_CHECKS
|
||||||
if (decn_is_zero(x)){
|
if (decn_is_zero(x)){
|
||||||
set_dec80_NaN(acc);
|
set_dec80_NaN(acc);
|
||||||
|
#ifdef DESKTOP
|
||||||
|
printf("error division by 0\n");
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -775,6 +791,20 @@ int8_t decn_to_str(char* buf, const dec80* x){
|
|||||||
uint8_t use_sci = 0;
|
uint8_t use_sci = 0;
|
||||||
static __xdata dec80 tmp;
|
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 and normalize
|
||||||
copy_decn(&tmp, x);
|
copy_decn(&tmp, x);
|
||||||
remove_leading_zeros(&tmp);
|
remove_leading_zeros(&tmp);
|
||||||
|
@ -19,6 +19,7 @@ extern "C" {
|
|||||||
//allow full range, but reserve -16384 for special numbers
|
//allow full range, but reserve -16384 for special numbers
|
||||||
#define DEC80_MIN_EXP (-16383)
|
#define DEC80_MIN_EXP (-16383)
|
||||||
#define DEC80_MAX_EXP 16383
|
#define DEC80_MAX_EXP 16383
|
||||||
|
#define DEC80_NAN_EXP (-16383 - 1)
|
||||||
|
|
||||||
//decimal80 unpacked into 80 bits
|
//decimal80 unpacked into 80 bits
|
||||||
// for computation
|
// 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_zero(dec80* dest);
|
||||||
void set_dec80_NaN(dec80* dest);
|
void set_dec80_NaN(dec80* dest);
|
||||||
|
uint8_t decn_is_nan(const dec80* x);
|
||||||
|
|
||||||
void negate_decn(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
|
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