Floating Point Input and Ouput

From Nutwiki
Jump to: navigation, search

Test Environments

Hardware Comments Nut/OS
4.8.7
Ethernut 1.3 H OK
Binaries
Compiler: AVR-GCC 4.3.2
Ethernut 2.1 B OK
Binaries
Compiler: AVR-GCC 4.3.2
Ethernut 3.0 E NO

Overview

While Nut/OS doesn't provide floating point math functionality by default, it is still there. This example explains how to use floating point values in printf and scanf statements.

Before you begin, please enable floating point support for your project. In order to do this, open the configurator, load the appropriate config file for your project and then activate the following option:

File:Floatactivation.png

Now rebuild Nut/OS to apply the changed configuration.

Source Code

<source lang="c">

  1. include <dev/board.h>
  2. include <stdio.h>
  3. include <io.h>

int main(void) {

   unsigned long baud = 115200;
   double val = 0.0;
   double val2 = 0.0;
   NutRegisterDevice(&DEV_UART, 0, 0);
   freopen(DEV_UART_NAME, "w", stdout);
   freopen(DEV_UART_NAME, "r", stdin);
   _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
   puts("\nNut/OS Floating Point Input and Output Demo");
   puts("\nPlease enter a floating point value:");
   scanf("%lf", &val);
   printf("\nYou entered: %lf\nThe exponential notation of this is: %e\nThe shorter version of those is: %G", val, val, val);
   puts("\n\nPlease enter another floating point value:");
   scanf("%lf", &val2);
   printf("Let's do some math with those numbers.\n%lf + %lf = %lf\n%lf - %lf = %lf\n%lf * %lf = %lf\n%lf / %lf = %lf\n", val,
          val2, (val + val2), val, val2, (val - val2), val, val2, (val * val2), val, val2, (val / val2));
   printf
       ("And in case you want your floats shorter take a look at this:\n%.2lf\n%.4lf\n\nThat concludes the demonstration. Thanks for testing!",
        val, val2);
   for (;;);
   return 0;

} </source>

Details

<source lang="c"> unsigned long baud = 115200; double val = 0.0; double val2 = 0.0;

NutRegisterDevice(&DEV_UART, 0, 0); freopen(DEV_UART_NAME, "w", stdout); freopen(DEV_UART_NAME, "r", stdin); _ioctl(_fileno(stdout), UART_SETSPEED, &baud); </source>

Upon first look, this appears to be our default initialization and setup. But look again. This example is going to be about floats, isn't it? So why are there none? And what are the doubles needed for?

Technically, Nut/OS knows about floats once you activate floating point support. Still, the compiler checks all expect doubles to be passed as floating point values. This is no problem, since (at least in the case of Nut/OS) floats and doubles occupy the same amount of RAM and the formats can be cast to each other without any data loss.

In order to avoid compiler warnings, we declare our floats as doubles. We will still use them as floats, though. If you don't care about compiler warnings, you can change the 'double' to 'float' here.

<source lang="c"> puts("\nNut/OS Floating Point Input and Output Demo");

puts("\nPlease enter a floating point value:"); scanf("%lf", &val); </source>

Now we output a name for the program and then ask the user to enter a floating point value. Floats can be entered using the %f, %F, %lf or %LF format specifier. Depending on the platform they may behave slightly different from each other but in general they all mean the same.

<source lang="c"> printf("\nYou entered: %lf\nThe exponential notation of this is: %e\nThe shorter version of those is: %G", val, val, val); </source>

Now that we have a float we can work with it. First of all let's output it in some different formats.

The %e and %E format specifiers will output the number in exponential notation.

The %g and %G format specifiers are supposed to output either the %f or the %e rendition of the number, whichever is shorter. I couldn't get this to work properly, though, it always returned the exponential notation.

<source lang="c"> puts("\n\nPlease enter another floating point value:"); scanf("%lf", &val2); </source>

What good would a floating point example be without some math? Let's ask the user for another number.

<source lang="c"> printf("Let's do some math with those numbers.\n%lf + %lf = %lf\n%lf - %lf = %lf\n%lf * %lf = %lf\n%lf / %lf = %lf\n", val,

      val2, (val + val2), val, val2, (val - val2), val, val2, (val * val2), val, val2, (val / val2));

</source>

This printf has a long parameter list. That is because we add, subtract, multiply and divide our two numbers all after each other, displaying the calculation and the result in each line. The actual calculations are the values in parentheses.

Note how no typecasting or anything else is necessary for the floating point math to work. It just does. Neat, eh?

<source lang="c"> printf

   ("And in case you want your floats shorter take a look at this:\n%.2lf\n%.4lf\n\nThat concludes the demonstration. Thanks for testing!",
    val, val2);

</source>

Floats also support further customization during output. By prefixing the format specifier with "." and a number we can specify the number of digits we want to print after the decimal dot.

If you want to add a maximum number limit before the dot, you can do that, too. Just type something like "%2.3lf" and your number can be customized even further.

Output

<source lang="text"> Nut/OS Floating Point Input and Output Demo

Please enter a floating point value: 3.1415 You entered: 3.141500 The exponential notation of this is: 3.141500e+00 The shorter version of those is: 3.141500e+00

Please enter another floating point value: Let's do some math with those numbers. 3.141500 + 1.412000 = 4.553500 3.141500 - 1.412000 = 1.729500 3.141500 * 1.412000 = 4.435798 3.141500 / 1.412000 = 2.224858 And in case you want your floats shorter take a look at this: 3.14 1.4120 </source>

See also