为什么奇数*偶数在C中不返回精确值?
完成我的项目(使用带有键盘 4x4、LCD 和 4 LED 的 PIC18 的计算器)后,我在乘法运算中遇到了奇怪的问题
当乘以奇数 (> 1) * 偶数 (> 0) 时,结果并不完全正确,对于例如, 3 * 4 = 11.99999
====================
这里我尝试描述一下情况:
用户按下了键盘,然后程序从键盘获取字符并将其存储到 char[](一次一个字符)中,所以最终我们有两个 char[] Operand[13] 和 Operand[13]。输入 Operand1 和 Operand2 后,程序使用 atof() 函数将其转换为浮点数,然后应用一些运算(“+”、“-”、“*”或“/”)并将结果存储在 int Result 中。最后,程序使用 FloatToStr() 函数将此 int 转换为 char[] 并将其显示在 LCD 上。
=====================
这是我的代码:(抱歉,有点长,但我希望你帮我解决这个问题)
unsigned char Key[4][4] = {{'1','2','3','4'}, // Keypad 4x4 Matrix
{'5','6','7','8'},
{'9','0','.','E'},
{'+','-','*','/'}};
unsigned char Operand_String[2][13], Operation_String, Result_String[15]; // Where we store the operand, operation & Result as chars
unsigned char Row, Column; // Row & Column determine the location of Key in the Keypad matrix that the user pressed
unsigned char State; // 1: Operand1 - 2: Operand2 - 3: Operation - 4: Result
unsigned int EntryCount; // Counter for counts entries on LCD
unsigned int Operand1_length, Operand2_length; // Lengths of Operand1 & Operand2
bit Direction; // 1: right - 0: left
bit Operand1_Sign, Operand2_Sign; // 1: negative - 0: positive
signed float Operand1, Operand2, Result; // Fields where we store Operand1, Operand2 and Result
typedef unsigned int boolean; // ** DEFINING **
#define false 0 // ** BOOLEAN **
#define true (!false) // ** TYPE **
boolean ButtonIsPressed = false; // Flag that indicates whether a button is pressed or no button is pressed
boolean FloatingPointIncluded = false; // Flag that indicates if there is a floating point in the LCD or not
boolean Operand1_signed = false; // Flag that indicates if Operand1 has a sign or not
boolean Operand2_signed = false; // Flag that indicates if Operand2 has a sign or not
// ***** Lcd pinout settings *****
sbit LCD_RS at RD4_bit;
sbit LCD_EN at RD5_bit;
sbit LCD_D7 at RD3_bit;
sbit LCD_D6 at RD2_bit;
sbit LCD_D5 at RD1_bit;
sbit LCD_D4 at RD0_bit;
// ***** Pin Direction *****
sbit LCD_RS_Direction at TRISD4_bit;
sbit LCD_EN_Direction at TRISD5_bit;
sbit LCD_D7_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD0_bit;
// ***** End LCD module connections *****
// ***** Method that determines no. of Row and Column of keypad matrix where the user presses the button of that location on the keypad *****
void scan_key()
{
unsigned char portValue[4][4] = {{0b11101110, 0b11101101, 0b11101011, 0b11100111},
{0b11011110, 0b11011101, 0b11011011, 0b11010111},
{0b10111110, 0b10111101, 0b10111011, 0b10110111},
{0b01111110, 0b01111101, 0b01111011, 0b01110111}};
unsigned char temp[4] = {0B11111110, 0B11111101, 0B11111011, 0B11110111};
unsigned int loop_col = 1;
unsigned int loop_row = 1;
for (loop_col = 1; loop_col < 5; loop_col++)
{
PORTB = temp[loop_col - 1];
for (loop_row = 1; loop_row < 5; loop_row++)
{
if ( PORTB == portValue[loop_row - 1][loop_col - 1])
{
Row = loop_row;
Column = loop_col;
return;
}
}
PORTB = 0B11110000;
}
}
// ***** Interrupt Service Routine (ISR) *****
void interrupt() org 0x08
{
if (INTCON.TMR0IF) // Timer0 Interrupt
{
scan_key();
//Delay_ms(40);
INTCON.RBIE = 1;
INTCON.TMR0IF = 0;
}
else if (INTCON.RBIF) // PORTB Interrupt
{
INTCON.TMR0IF = 1;
INTCON.TMR0IE = 1;
INTCON.RBIE = 0;
INTCON.RBIF = 0;
ButtonIsPressed = true;
}
}
// ***** Method that calculates the result of the arithmatic Operation *****
float CalculateResult()
{
Operand1 = atof(Operand_String[0]);
Operand2 = atof(Operand_String[1]);
if(Operand1_sign == 1) Operand1 = - Operand1;
if(Operand2_sign == 1) Operand2 = - Operand2;
switch(Operation_String)
{
case '+': Result = Operand1 + Operand2; break;
case '-': Result = Operand1 - Operand2; break;
case '*': Result = Operand1 * Operand2; break;
case '/': Result = Operand1 / Operand2; break;
}
return Result;
}
// ***** Method that makes LEDs blink *****
void LEDsBlink(int iteration)
{
char PORTA_Temp;
int i;
PORTA_Temp = PORTA;
if(iteration < 0)
{
PORTA = ~PORTA;
Delay_ms(200);
}
else
{
for(i = 0; i < iteration; i++)
{
PORTA = 0x0F;
Delay_ms(50);
PORTA = 0x00;
Delay_ms(50);
}
PORTA = PORTA_Temp;
}
}
// ***** Method that resets the variables *****
void Reset_Values()
{
EntryCount = 0;
State = 1;
Row = 0;
Column = 0;
Direction = 0;
Operand1_Sign = 0;
Operand2_Sign = 0;
Operand1 = 0;
Operand2 = 0;
Result = 0;
memset(Operand_String, 0, 2 * 13);
memset(Result_String, 0, 15);
ButtonIsPressed = false;
Operand1_signed = false;
Operand2_signed = false;
PORTA = 0x0F; // Turn on the 4 LEDs
}
void main()
{
// ***** Initializations of PIC18F4550 *****
TRISA = 0; // Configure the 4 LEDs as output
PORTA = 0x0F; // Turn on the 4 LEDs
TRISB = 0xF0; // Configure RB0 ~ RB3 as outputs & RB4 ~ RB7 as inputs
PORTB = 0xF0; // Assign 0xF0
OSCCON = 0x63; // 4 MHz - Internal oscillator
INTCON2.B7 = 0; // PORTB pull-ups are enabled by individual port latch values
INTCON.RBIF = 0; // Reset the interrupt flag
INTCON.RBIE = 1; // RB Change interrupt ON
INTCON.GIE = 1; // Global interrupts ON
ADCON1 = 0b00001111; // Digital inputs
// ***** Initializations of LCD *****
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear LCD
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1, 2, "Fouad Al-Malki"); // ** WELCOME **
Lcd_Out(2, 4, "CALCULATOR"); // ** MESSAGE **
Delay_ms(2000); // delay for 2 seconds
Lcd_Cmd(_LCD_CLEAR); // Clear DCD
Lcd_Out(1, 4, "Operand1: "); // Write "Operand1: " at first row
Lcd_Cmd(_LCD_SECOND_ROW); // Make current position at second row
Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on
// ***** Reset all values *****
Reset_Values();
while(1)
{
// ***** Control of LCD *****
if(ButtonIsPressed)
{
if(State == 1)
{
if(Key[row-1][column-1] != 'E')
{
if((EntryCount <= 13 && Key[row-1][column-1] != '+' && Key[row-1][column-1] != '-' && Key[row-1][column-1] != '/' && Key[row-1][column-1] != '*'))
{
if((Key[row-1][column-1] == '.' && !FloatingPointIncluded && EntryCount > 0) || Key[row-1][column-1] != '.')
{
Lcd_Chr_Cp(Key[row-1][column-1]);
Operand_String[0][EntryCount] = Key[row-1][column-1];
EntryCount++;
if(Key[row-1][column-1] == '.') FloatingPointIncluded = true;
}
else LEDsBlink(3);
}
else if(!Operand1_signed && EntryCount == 0 && (Key[row-1][column-1] == '+' || Key[row-1][column-1] == '-'))
{
if(Key[row-1][column-1] == '+') Operand1_Sign = 0;
else if(Key[row-1][column-1] == '-') Operand1_Sign = 1;
Lcd_Chr_Cp(Key[row-1][column-1]);
Operand1_signed = true;
}
else LEDsBlink(3);
}
else if(Key[row-1][column-1] == 'E' && EntryCount != 0)
{
State = 2;
FloatingPointIncluded = false;
Operand1_length = EntryCount;
EntryCount = 0;
Row = 0;
Column = 0;
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1, 4, "Operand2: ");
Lcd_Cmd(_LCD_SECOND_ROW);
Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on
if(PORTA.B0 == 1)
{
PORTA = 0x08;
}
}
else LEDsBlink(3);
}
else if(State == 2)
{
if(Key[row-1][column-1] != 'E')
{
if((EntryCount <= 13 && Key[row-1][column-1] != '+' && Key[row-1][column-1] != '-' && Key[row-1][column-1] != '/' && Key[row-1][column-1] != '*'))
{
if((Key[row-1][column-1] == '.' && !FloatingPointIncluded && EntryCount > 0) || Key[row-1][column-1] != '.')
{
Lcd_Chr_Cp(Key[row-1][column-1]);
Operand_String[1][EntryCount] = Key[row-1][column-1];
EntryCount++;
if(Key[row-1][column-1] == '.') FloatingPointIncluded = true;
}
else LEDsBlink(3);
}
else if(!Operand2_signed && EntryCount == 0 && (Key[row-1][column-1] == '+' || Key[row-1][column-1] == '-'))
{
if(Key[row-1][column-1] == '+') Operand2_Sign = 0;
else if(Key[row-1][column-1] == '-') Operand2_Sign = 1;
Lcd_Chr_Cp(Key[row-1][column-1]);
Operand2_signed = true;
}
else LEDsBlink(3);
}
else if(Key[row-1][column-1] == 'E' && EntryCount != 0)
{
State = 3;
FloatingPointIncluded = false;
Operand2_length = EntryCount;
EntryCount = 0;
Row = 0;
Column = 0;
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1, 4, "Operation: ");
Lcd_Cmd(_LCD_SECOND_ROW);
Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on
if(PORTA.B0 == 1)
{
PORTA = PORTA << 1;
Direction = 0;
}
}
else LEDsBlink(3);
}
else if(State == 3)
{
if(Key[row-1][column-1] != 'E')
{
if(EntryCount == 0 && (Key[row-1][column-1] == '+' || Key[row-1][column-1] == '-' || Key[row-1][column-1] == '/' || Key[row-1][column-1] == '*'))
{
Lcd_Chr_Cp(Key[row-1][column-1]);
Operation_String = Key[row-1][column-1];
EntryCount++;
}
else LEDsBlink(3);
}
else if(Key[row-1][column-1] == 'E' && EntryCount != 0)
{
State = 4;
FloatingPointIncluded = false;
EntryCount = 0;
Row = 0;
Column = 0;
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1, 3, "The Result: ");
Lcd_Cmd(_LCD_SECOND_ROW);
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Result = CalculateResult();
//printOut(Result, "/*rn");
FloatToStr(Result, Result_String);
Lcd_Out(2,1,Result_String);
PORTA = 0x0F;
}
else LEDsBlink(3);
}
else if(State == 4)
{
if(Key[row-1][column-1] == 'E')
{
Reset_Values();
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1, 4, "Operand1: ");
Lcd_Cmd(_LCD_SECOND_ROW);
Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on
PORTA == 0x0F;
}
}
ButtonIsPressed = false;
}
// ***** Control of LEDs *****
else
{
if(State == 1)
{
if(PORTA == 0x0F) PORTA = 0x01;
Delay_ms(300);
if(PORTA < 0x08) PORTA = PORTA << 1;
if(PORTA == 0x08)
{
Delay_ms(300);
PORTA = 0x01;
}
}
if(State == 2)
{
Delay_ms(300);
PORTA = PORTA >> 1;
if(STATUS.C == 1)
{
PORTA = 0x08;
STATUS.C = 0;
}
}
if(State == 3)
{
Delay_ms(300);
if (Direction == 0) {
PORTA = PORTA >> 1;
if (PORTA.B0 == 1) Direction = 1;
}
else
{
PORTA = PORTA << 1;
if (PORTA.B3 == 1) Direction = 0;
}
}
if(State == 4)
{
LEDsBlink(-1);
}
}
}
}
After finishing my project (The Calculator using PIC18 with Keypad 4x4, LCD and 4 LEDs), I faced wierd issue in the multiplication operation
When multiply odd (> 1) * even (> 0) the result is not exactly correct, for example, 3 * 4 = 11.99999
====================
Here I would try to descripe the situation:
The user press a button of the keypad, then the program takes the char from the keypad and stores it into char[] (A char at a time) so finally we have two char[] Operand[13] and Operand[13]. After Entering Operand1 and Operand2 the program converts it to floating number using atof() function then apply some operation ('+', '-', '*' or '/') and stores the result in int Result. Finally, the program convert this int to char[] using FloatToStr() function and display it on the LCD.
=====================
Here is my code: (Sorry, it's kinda long but I want you help me solving this issue)
unsigned char Key[4][4] = {{'1','2','3','4'}, // Keypad 4x4 Matrix
{'5','6','7','8'},
{'9','0','.','E'},
{'+','-','*','/'}};
unsigned char Operand_String[2][13], Operation_String, Result_String[15]; // Where we store the operand, operation & Result as chars
unsigned char Row, Column; // Row & Column determine the location of Key in the Keypad matrix that the user pressed
unsigned char State; // 1: Operand1 - 2: Operand2 - 3: Operation - 4: Result
unsigned int EntryCount; // Counter for counts entries on LCD
unsigned int Operand1_length, Operand2_length; // Lengths of Operand1 & Operand2
bit Direction; // 1: right - 0: left
bit Operand1_Sign, Operand2_Sign; // 1: negative - 0: positive
signed float Operand1, Operand2, Result; // Fields where we store Operand1, Operand2 and Result
typedef unsigned int boolean; // ** DEFINING **
#define false 0 // ** BOOLEAN **
#define true (!false) // ** TYPE **
boolean ButtonIsPressed = false; // Flag that indicates whether a button is pressed or no button is pressed
boolean FloatingPointIncluded = false; // Flag that indicates if there is a floating point in the LCD or not
boolean Operand1_signed = false; // Flag that indicates if Operand1 has a sign or not
boolean Operand2_signed = false; // Flag that indicates if Operand2 has a sign or not
// ***** Lcd pinout settings *****
sbit LCD_RS at RD4_bit;
sbit LCD_EN at RD5_bit;
sbit LCD_D7 at RD3_bit;
sbit LCD_D6 at RD2_bit;
sbit LCD_D5 at RD1_bit;
sbit LCD_D4 at RD0_bit;
// ***** Pin Direction *****
sbit LCD_RS_Direction at TRISD4_bit;
sbit LCD_EN_Direction at TRISD5_bit;
sbit LCD_D7_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD0_bit;
// ***** End LCD module connections *****
// ***** Method that determines no. of Row and Column of keypad matrix where the user presses the button of that location on the keypad *****
void scan_key()
{
unsigned char portValue[4][4] = {{0b11101110, 0b11101101, 0b11101011, 0b11100111},
{0b11011110, 0b11011101, 0b11011011, 0b11010111},
{0b10111110, 0b10111101, 0b10111011, 0b10110111},
{0b01111110, 0b01111101, 0b01111011, 0b01110111}};
unsigned char temp[4] = {0B11111110, 0B11111101, 0B11111011, 0B11110111};
unsigned int loop_col = 1;
unsigned int loop_row = 1;
for (loop_col = 1; loop_col < 5; loop_col++)
{
PORTB = temp[loop_col - 1];
for (loop_row = 1; loop_row < 5; loop_row++)
{
if ( PORTB == portValue[loop_row - 1][loop_col - 1])
{
Row = loop_row;
Column = loop_col;
return;
}
}
PORTB = 0B11110000;
}
}
// ***** Interrupt Service Routine (ISR) *****
void interrupt() org 0x08
{
if (INTCON.TMR0IF) // Timer0 Interrupt
{
scan_key();
//Delay_ms(40);
INTCON.RBIE = 1;
INTCON.TMR0IF = 0;
}
else if (INTCON.RBIF) // PORTB Interrupt
{
INTCON.TMR0IF = 1;
INTCON.TMR0IE = 1;
INTCON.RBIE = 0;
INTCON.RBIF = 0;
ButtonIsPressed = true;
}
}
// ***** Method that calculates the result of the arithmatic Operation *****
float CalculateResult()
{
Operand1 = atof(Operand_String[0]);
Operand2 = atof(Operand_String[1]);
if(Operand1_sign == 1) Operand1 = - Operand1;
if(Operand2_sign == 1) Operand2 = - Operand2;
switch(Operation_String)
{
case '+': Result = Operand1 + Operand2; break;
case '-': Result = Operand1 - Operand2; break;
case '*': Result = Operand1 * Operand2; break;
case '/': Result = Operand1 / Operand2; break;
}
return Result;
}
// ***** Method that makes LEDs blink *****
void LEDsBlink(int iteration)
{
char PORTA_Temp;
int i;
PORTA_Temp = PORTA;
if(iteration < 0)
{
PORTA = ~PORTA;
Delay_ms(200);
}
else
{
for(i = 0; i < iteration; i++)
{
PORTA = 0x0F;
Delay_ms(50);
PORTA = 0x00;
Delay_ms(50);
}
PORTA = PORTA_Temp;
}
}
// ***** Method that resets the variables *****
void Reset_Values()
{
EntryCount = 0;
State = 1;
Row = 0;
Column = 0;
Direction = 0;
Operand1_Sign = 0;
Operand2_Sign = 0;
Operand1 = 0;
Operand2 = 0;
Result = 0;
memset(Operand_String, 0, 2 * 13);
memset(Result_String, 0, 15);
ButtonIsPressed = false;
Operand1_signed = false;
Operand2_signed = false;
PORTA = 0x0F; // Turn on the 4 LEDs
}
void main()
{
// ***** Initializations of PIC18F4550 *****
TRISA = 0; // Configure the 4 LEDs as output
PORTA = 0x0F; // Turn on the 4 LEDs
TRISB = 0xF0; // Configure RB0 ~ RB3 as outputs & RB4 ~ RB7 as inputs
PORTB = 0xF0; // Assign 0xF0
OSCCON = 0x63; // 4 MHz - Internal oscillator
INTCON2.B7 = 0; // PORTB pull-ups are enabled by individual port latch values
INTCON.RBIF = 0; // Reset the interrupt flag
INTCON.RBIE = 1; // RB Change interrupt ON
INTCON.GIE = 1; // Global interrupts ON
ADCON1 = 0b00001111; // Digital inputs
// ***** Initializations of LCD *****
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear LCD
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1, 2, "Fouad Al-Malki"); // ** WELCOME **
Lcd_Out(2, 4, "CALCULATOR"); // ** MESSAGE **
Delay_ms(2000); // delay for 2 seconds
Lcd_Cmd(_LCD_CLEAR); // Clear DCD
Lcd_Out(1, 4, "Operand1: "); // Write "Operand1: " at first row
Lcd_Cmd(_LCD_SECOND_ROW); // Make current position at second row
Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on
// ***** Reset all values *****
Reset_Values();
while(1)
{
// ***** Control of LCD *****
if(ButtonIsPressed)
{
if(State == 1)
{
if(Key[row-1][column-1] != 'E')
{
if((EntryCount <= 13 && Key[row-1][column-1] != '+' && Key[row-1][column-1] != '-' && Key[row-1][column-1] != '/' && Key[row-1][column-1] != '*'))
{
if((Key[row-1][column-1] == '.' && !FloatingPointIncluded && EntryCount > 0) || Key[row-1][column-1] != '.')
{
Lcd_Chr_Cp(Key[row-1][column-1]);
Operand_String[0][EntryCount] = Key[row-1][column-1];
EntryCount++;
if(Key[row-1][column-1] == '.') FloatingPointIncluded = true;
}
else LEDsBlink(3);
}
else if(!Operand1_signed && EntryCount == 0 && (Key[row-1][column-1] == '+' || Key[row-1][column-1] == '-'))
{
if(Key[row-1][column-1] == '+') Operand1_Sign = 0;
else if(Key[row-1][column-1] == '-') Operand1_Sign = 1;
Lcd_Chr_Cp(Key[row-1][column-1]);
Operand1_signed = true;
}
else LEDsBlink(3);
}
else if(Key[row-1][column-1] == 'E' && EntryCount != 0)
{
State = 2;
FloatingPointIncluded = false;
Operand1_length = EntryCount;
EntryCount = 0;
Row = 0;
Column = 0;
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1, 4, "Operand2: ");
Lcd_Cmd(_LCD_SECOND_ROW);
Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on
if(PORTA.B0 == 1)
{
PORTA = 0x08;
}
}
else LEDsBlink(3);
}
else if(State == 2)
{
if(Key[row-1][column-1] != 'E')
{
if((EntryCount <= 13 && Key[row-1][column-1] != '+' && Key[row-1][column-1] != '-' && Key[row-1][column-1] != '/' && Key[row-1][column-1] != '*'))
{
if((Key[row-1][column-1] == '.' && !FloatingPointIncluded && EntryCount > 0) || Key[row-1][column-1] != '.')
{
Lcd_Chr_Cp(Key[row-1][column-1]);
Operand_String[1][EntryCount] = Key[row-1][column-1];
EntryCount++;
if(Key[row-1][column-1] == '.') FloatingPointIncluded = true;
}
else LEDsBlink(3);
}
else if(!Operand2_signed && EntryCount == 0 && (Key[row-1][column-1] == '+' || Key[row-1][column-1] == '-'))
{
if(Key[row-1][column-1] == '+') Operand2_Sign = 0;
else if(Key[row-1][column-1] == '-') Operand2_Sign = 1;
Lcd_Chr_Cp(Key[row-1][column-1]);
Operand2_signed = true;
}
else LEDsBlink(3);
}
else if(Key[row-1][column-1] == 'E' && EntryCount != 0)
{
State = 3;
FloatingPointIncluded = false;
Operand2_length = EntryCount;
EntryCount = 0;
Row = 0;
Column = 0;
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1, 4, "Operation: ");
Lcd_Cmd(_LCD_SECOND_ROW);
Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on
if(PORTA.B0 == 1)
{
PORTA = PORTA << 1;
Direction = 0;
}
}
else LEDsBlink(3);
}
else if(State == 3)
{
if(Key[row-1][column-1] != 'E')
{
if(EntryCount == 0 && (Key[row-1][column-1] == '+' || Key[row-1][column-1] == '-' || Key[row-1][column-1] == '/' || Key[row-1][column-1] == '*'))
{
Lcd_Chr_Cp(Key[row-1][column-1]);
Operation_String = Key[row-1][column-1];
EntryCount++;
}
else LEDsBlink(3);
}
else if(Key[row-1][column-1] == 'E' && EntryCount != 0)
{
State = 4;
FloatingPointIncluded = false;
EntryCount = 0;
Row = 0;
Column = 0;
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1, 3, "The Result: ");
Lcd_Cmd(_LCD_SECOND_ROW);
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Result = CalculateResult();
//printOut(Result, "/*rn");
FloatToStr(Result, Result_String);
Lcd_Out(2,1,Result_String);
PORTA = 0x0F;
}
else LEDsBlink(3);
}
else if(State == 4)
{
if(Key[row-1][column-1] == 'E')
{
Reset_Values();
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1, 4, "Operand1: ");
Lcd_Cmd(_LCD_SECOND_ROW);
Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on
PORTA == 0x0F;
}
}
ButtonIsPressed = false;
}
// ***** Control of LEDs *****
else
{
if(State == 1)
{
if(PORTA == 0x0F) PORTA = 0x01;
Delay_ms(300);
if(PORTA < 0x08) PORTA = PORTA << 1;
if(PORTA == 0x08)
{
Delay_ms(300);
PORTA = 0x01;
}
}
if(State == 2)
{
Delay_ms(300);
PORTA = PORTA >> 1;
if(STATUS.C == 1)
{
PORTA = 0x08;
STATUS.C = 0;
}
}
if(State == 3)
{
Delay_ms(300);
if (Direction == 0) {
PORTA = PORTA >> 1;
if (PORTA.B0 == 1) Direction = 1;
}
else
{
PORTA = PORTA << 1;
if (PORTA.B3 == 1) Direction = 0;
}
}
if(State == 4)
{
LEDsBlink(-1);
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您使用的是浮点类型,在某些数学运算下并不总是保证能够完全准确地表示浮点类型。
可能值得进行某种检查以查看其中一个或两个操作数是否为整数,然后如果可以的话使用
int
类型。You're using float types, which aren't always guaranteed to be represented with complete accuracy under some mathematical operations.
It might be worth doing some sort of check to see if either or both of the operands are integers, and then use an
int
type if you can.原因是它在内部存储为二进制浮点,而不是十进制浮点,这意味着一些容易用十进制表示的数字不可能完全准确地用二进制表示,因此四舍五入到最接近的可能值。
The reason is it is stored as binary floating-point, not decimal floating-point internally, meaning some numbers easily represented in decimal are impossible to represent to full accuracy in binary, and so are rounded to the closest possible value.
通常,像这样的两个小整数浮点数的直接乘法会产生
x.0
结果。然而,对于更复杂的浮点数学,您确实必须采取这样的态度:任何结果都是估计,并且会存在一定的少量误差。通常它取决于输入中的错误量,但至少您应该将仅在最后一个可表示数字中出现的任何结果视为“正确”。一般来说,期望从浮点数学中得到精确答案是错误的。另请注意,在本例中,它似乎试图告诉您答案是 11.9(9 个重复)。从数学上讲,这与 12 相同。所以我不会真正考虑这个答案,因为它提出了“错误”。
Normally a straight multiplication of two small integer floats like that would produce a
x.0
result. However, for more complicated floating-point math you really have to take the attitude that any results are estimates and there will be a certian small amount of error. Often it depends on the amount of error in the inputs, but at the least you should consider any result that is only off in the last representable digit as "correct". In general, expecting exact answers out of floating-point math is wrong.Also note that in this case it appears to be attempting to tell you that the answer is 11.9(9 repeating). Mathematically that is the same as 12. So I wouldn't really consider this answer it is coming up with "wrong".