![]() | ![]() | ![]() |
| | |||||||
| General Electronics Chat This forum is for general chat about electronics, eg: Dont know what a part does? Dont know how to read a circuit? Want to get an opinion? |
| | LinkBack | Thread Tools | Display Modes |
| | (permalink) |
| I'm using Codevision AVR (C code) to program my Atmel uProcessors. I'm trying to get the bugs out of a piece of code and realised that it is rounding decimal numbers (1.5 3.14159 etc) to the whole number. After finding this, I realized I don't have any idea how to keep the decimal spaces without rounding. Any help is greatly appreciated! ~Mike
__________________ All Electronic components run on smoke. Let the smoke out and it no longer works. ~Tim Baker (Electronics Instructor at John A. Logan College) | |
| |
| | (permalink) | |
| Quote:
Far better to scale the values to be integers, and add the decimal point afterwards - as an example, you don't use money as $1.23 - you use 123 cents instead. But keeping on the rounding theme, you add 0.5 to the value, this rounds it to the nearest whole number - ASSUMING the maths routines are proper floating point!. | ||
| |
| | (permalink) |
| If it's rounding to whole numbers, then you aren't using float or double. In addition to the speed issue, most floating point arithmetic uses binary fractions, so you will get binary rounding in most cases. Most decimal fractions cannot be stored exactly as binary fractions. | |
| |
| | (permalink) |
| Ok, maybe It's right and my code for the LCD is wrong. As a test, I put in dt = 3.14159 but the LCD shows me 4048 when I print dt. Code: //Display on LCD lcd_clear(); sprintf(lcd_out, "Pi = %5d", dt); lcd_puts(lcd_out); ~Mike
__________________ All Electronic components run on smoke. Let the smoke out and it no longer works. ~Tim Baker (Electronics Instructor at John A. Logan College) | |
| |
| | (permalink) |
| If dt is float or double, you should be using one of the floating-point conversion codes. They are %e, %f, and %g. %e converts the number to "E" format, %f converts to fixed point format, and %g, if it exists in your compiler, automatically chooses between the other two. Check your C manual for formatted I/O. | |
| |
| | (permalink) |
| %e, %f, and %g don't work either. Code: float dt; dt = 3.14159; //Display on LCD lcd_clear(); sprintf(lcd_out, "Pi = %5e", dt); lcd_puts(lcd_out);
__________________ All Electronic components run on smoke. Let the smoke out and it no longer works. ~Tim Baker (Electronics Instructor at John A. Logan College) | |
| |
| | (permalink) |
| you got 4048 in the first code because you specified %d which is used for integers. you could give us the whole code and tell us what you're expecting. 4048 seems to be too far off 3.142? try using %f instead, if it doesn't work, check other parts of the code...
__________________ Everybody can but not everybody will. | |
| |
| | (permalink) |
| With %d, I get "Pi = 3" With %e, %f, and %g I get "Pi = 4048" The rest of the code has to do with my ballancing bot. The Pi thing really has nothing to do with the bot, I am just trying to get this number to display so that I know it is calculating the right numbers without rounding them.
__________________ All Electronic components run on smoke. Let the smoke out and it no longer works. ~Tim Baker (Electronics Instructor at John A. Logan College) | |
| |
| | (permalink) |
| One way I can get a result of 3 for float dt and %d is if all numbers are stored Big-Endian. But that would also imply a non-IEEE floating-point format (because of the exponent range, not the byte ordering). I would have expected the result to be the opposite, with %d showing a wild number, and the %e, %f, and %g showing a rounded result. As an example of %f, you would normally use %8.3f to create at least 8 characters containing 3 decimal digits in the fraction. | |
| |
| | (permalink) |
| As has been said, using float or double is a bad idea since they're slow as hell to do math on. Microcontrollers have no hardware resources to do floating point ops and performing them is like 1000x slower than integer ops. Generally when we need to work with decimals on a controller, it is best to simply multiply it so the desired accuracy is achieved. For example unsigned int can store values 0-65535. You could deal with Pi as Pi*10,000, Pi*100, Pi*2^14, or Pi*2^8, etc. As always, you will need to evaluate your math carefully to ensure that nowhere will a math operation overflow the storage type being used. This is true regardless of whether a multiplier is used or not. Also research "integer promotion" which is how C normally does math, this will directly affect when a calculation will overflow. Your display code will need to do some tricks to take 314159 and display as 3.14159. A string processing task could be told to make a string out of the number and add a decimal 5 places over. Code: void sprintdec(char *ptr, unsigned int number, unsigned char shift); When stating this in your code you will probably want to take advantage of constant folding. For example: Code: #define DEC_MULT 10000 unsigned int myInt= 3.14159f * DEC_MULT;
__________________ I thought what I'd do was I'd pretend I was one of those deaf-mutes. | |
| |
| | (permalink) |
| Thanks for the ideas. I think I'll just have to multiply the numbers and divide the results. When the robot is complete, I'm not going to have to display these numbers, I was just using the LCD for troubleshooting and seeing if I was getting the values close to what they need to be. ~Mike
__________________ All Electronic components run on smoke. Let the smoke out and it no longer works. ~Tim Baker (Electronics Instructor at John A. Logan College) | |
| |
| | (permalink) |
| Hi MrMikey, Two things: First, it's probably not a bad idea to put an F at the end of your floating point constant, ie dt = 3.14159F; more importantly, it is possible you do not have the floating point support enabled in the compiler options. Look under Configure Project, C Compiler. The default setting for sprintf support is int only - select 'float, width, precision' to get the floating point support in. When you do that, you will discover why floating point is such a bad idea - your code will grow quite a bit, as the floating point library gets pulled in. Mike. | |
| |
| | (permalink) |
| Hey Mike, that was the problem. My code isn't all the big, I have plenty of room on the chip. I'll probably use floating points to get it working first, then if its going to slow, I can convert it over to optimize the code when I get it running. Thanks! ~Mike
__________________ All Electronic components run on smoke. Let the smoke out and it no longer works. ~Tim Baker (Electronics Instructor at John A. Logan College) | |
| |