0.4.1 printHelpers

This commit is contained in:
Rob Tillaart 2023-07-15 09:44:38 +02:00
parent d70def77dc
commit 669feb85f8
11 changed files with 289 additions and 38 deletions

View File

@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.4.1] - 2023-07-13
- fix #16 signed/unsigned warning
- update example **print_toRoman.ino** to print 1..5000
- update example **print_sci.ino** when double = 8 bytes.
- update readme.md
- fix description range **toBytes()**
- change return type of **size_t sci(Stream, value, decimals)**
- add **printInch(inch, step)** e.g 7 7/16
- add **printFeet(feet)**
## [0.4.0] - 2023-01-28
- bump version number as fix in 0.3.1 was serious
- add **toRoman()**

View File

@ -24,9 +24,13 @@ data in a way not possible in the standard print library of the Arduino.
- **hex()** generates hexadecimal output with leading zeros up to **uint64_t**.
- **bin()** generates binary output with leading zeros up to **uint64_t**.
- **toRoman()** generates a ROMAN representation of a (positive) number.
- **printInch(float inch, uint16_t step)** experimental.
- **printFeet(float feet)** experimental.
Details, see below.
If a (generic) print format is missing, please open an issue.
#### Thread safety
@ -48,31 +52,36 @@ The following functions are implemented:
#### print64()
- **char \* print64(int64_t value, uint8_t base)** converts a 64 bit integer
- **char \* print64(int64_t value, uint8_t base = 10)** converts a 64 bit integer
number to a char array.
The plus sign is not printed, neither are leading zero's.
Base 10 (DEC) and 16 (HEX) are supported and other bases up to 36 can be used.
Default base == 10 == decimal.
Note that negative numbers will always get a minus sign for any base.
Cast the number to uint64_t to suppress the sign.
- **char \* print64(uint64_t value, uint8_t base)** converts a unsigned 64 bit
- **char \* print64(uint64_t value, uint8_t base = 10)** converts a unsigned 64 bit
int number to a char array.
No sign is printed, neither are leading zero's.
Base 10 (DEC) and 16 (HEX) are supported and bases up to 36 can be used.
Default base == 10 == decimal.
#### sci() eng()
- **char \* sci(double value, uint8_t decimals)** converts a float or double to a
char array.
E.g. **print(sci(f, 4))** ==> results in "6.7407E+21".
E.g. **print(sci(f, 4))** ==> results in **"6.7407E+21"**.
The existing Arduino print library only supports printing of floats and
doubles up to about 4E9 while the range of floats goes up to ~1E38.
The smallest float values will often be printed as 0.00 while floats
support down to about 1E-38 (subnormal even to 1E-45).
Existing (AVR) library functions **dtostrf()** has no scientific notation
and **dtostre()** is limited to 7 decimals. These latter two are faster.
Values printed with **sci()** do look pretty in column output.
Values printed with **sci()** do look often pretty in column output.
- **size_t sci(Stream &str, double value, uint8_t decimals)** as above.
Prints directly to a stream, returning bytes printed.
- **char \* eng(double value, uint8_t decimals)** converts a float or double to a
char array.
@ -80,26 +89,27 @@ E.g. print(eng(f, 4)) ==> results in "6.7407E+21".
Note the exponent created by **eng()** is always a multiple of 3.
Values printed with **eng()** do not always look pretty in column output.
This is due to the exponent power of 3. However its output translates easy to
thousands, millions etc which are powers of 3.
thousands, millions, billions, and millis, micros, nano etc which are powers of 3.
- **char \* scieng(double value, uint8_t decimals, uint8_t exponentMultiple)** converts a
float or double to a char array.
**sci()** and **eng()** use the same underlying function called **scieng()**
as the initial code for converting was almost identical.
Although not intended to be used directly, one may use it.
Although not intended to be used directly, feel free to use it.
The last parameter **exponentMultiple** defines where the exponent is a multiple of.
For the **sci()** function this is 1, for the **eng()** function this is 3.
The **scieng()** function works for multiples from 1..9 for the exponent.
The usability of other values than 1 and 3 are not known.
Personally I like the multiple of 2 as I get 2 orders of magnitude in the
mantissa.
mantissa. This is e.g. useful for temperature Celsius or percentages.
#### toBytes()
- **char \* toBytes(double value, uint8_t decimals = 2)** makes from a big number
representing an amount of bytes a shorter string usable for displaying.
The number of decimals is max 3
- **char \* toBytes(double value, uint8_t decimals = 2)** converts a big number
representing an amount of bytes to a shorter string usable for displaying.
The string uses official extensions.
The number of decimals is max 3:
Example 3.292.528 ==> "3.140 MB"
Value ranges supported are in steps of powers of 1024.
@ -107,12 +117,13 @@ These will all be shown in UPPERCASE so KB, MB etc.
| Unit | abbrev. | size | Unit | abbrev. | size |
|:-----------:|:---------:|:--------:|:------------:|:---------:|:--------:|
| kilobytes | KB | 1024 | zettabytes | KB | 1024^7 |
| megabytes | MB | 1024^2 | yottabytes | MB | 1024^8 |
| gigabytes | GB | 1024^3 | xonaytes | GB | 1024^9 |
| terabytes | TB | 1024^4 | wekabytes | TB | 1024^10 |
| petabytes | PB | 1024^5 | vundabytes | PB | 1024^11 |
| exabytes | EB | 1024^6 | udabytes | EB | 1024^12 |
| bytes | B | 1024^0 | | | |
| kilobytes | KB | 1024^1 | zettabytes | ZB | 1024^7 |
| megabytes | MB | 1024^2 | yottabytes | YB | 1024^8 |
| gigabytes | GB | 1024^3 | xonaytes | XB | 1024^9 |
| terabytes | TB | 1024^4 | wekabytes | WB | 1024^10 |
| petabytes | PB | 1024^5 | vundabytes | VB | 1024^11 |
| exabytes | EB | 1024^6 | udabytes | UB | 1024^12 |
Treda Byte is shortened as "TDB" and uses 2 chars to indicate the magnitude.
@ -123,7 +134,7 @@ Should be big enough for some time.
Note: max uint64_t 2^64 is in the order of exa or zetta bytes.
To have some support for the really big sizes the code uses lowercase for the next 8 levels:
treda sorta rinta quexa pepta ocha nena minga luma (1024\^21 ~~ 10\^63)
treda sorta rinta quexa pepta ocha nena minga luma (1024\^13 ~~ 1024\^21)
To enable this patch the function in the **printHelpers.cpp** file.
@ -132,7 +143,7 @@ To enable this patch the function in the **printHelpers.cpp** file.
The default print() function of Arduino does not have leading zero's
for **HEX** and **BIN**.
This often causes a "broken" layout especially if one wants to print
in columns or so.
the output in columns or so.
To solve this the following functions are added that will generate a
constant length char array.
@ -151,6 +162,10 @@ Note: Data types not supported, must be cast to an supported type.
Note: There is overlap between **hex(value)** and **print64(value, HEX)**.
The latter does not produce the leading zero's or fixed length output.
Note: hex() does not print hex indicator like "0x" or "H" in front.
Note: bin() does not print bin indicator like "b" at the end.
#### toRoman()
@ -188,6 +203,18 @@ Notes:
"official" and extended numbers.
- The number 4 is often written as IIII on clocks with Roman digits,
although IV would be (more?) correct and therefore IV is used.
The reason for IIII is that it is opposite of VIII giving a visual balance.
#### Distance feet inch
Experimental 0.4.1
- **char \* printInch(float inch, uint16_t step = 16)** prints a float inch distance default in sixteenth ```a b/16```.
The parameter step must be a power of 2 == 2, 4, 8, 16, 32, 64, 128.
- **char \* printFeet(float feet)** prints a float feet distance as
``` a'b"``` e.g. 4.5 feet prints as ```4'6"```
## Shared print buffer
@ -230,6 +257,7 @@ When functions are added, the recommended minimum size might increase.
- documentation
- improve readability of the code
- em ==> exponentFactor?
#### Could
@ -239,15 +267,13 @@ When functions are added, the recommended minimum size might increase.
- investigate thread safe version
- pass char buffer as parameter (breaking)
- could be the log10 pow version?
- investigate distance print helpers.
- feet(float cm) as 3'2" or 3-7/8 feet
- inch(float cm) as 32"
- yards(float meter),
- miles(float kilometre)
- optimize **char \* hex(uint8_t / uint16_t ...)**
- make this library a .h file only?
#### Wont
- add **oct()** along BIN, HEX
- add **float()** as Arduino limits floats to "MAXLONG" by code.
- use dtostrf() - is that portable?
- use sci() or eng()
@ -260,3 +286,4 @@ When functions are added, the recommended minimum size might increase.
- **sci()** and **eng()**.
- investigate sci() version based upon use of log()
- done => see examples.

View File

@ -0,0 +1,40 @@
// FILE: print_inch_feet.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo program distance functions
#include "printHelpers.h"
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("PRINTHELPERS_VERSION: ");
Serial.println(PRINTHELPERS_VERSION);
// test some random values
for (float inch = 0; inch < 100; inch += 5.43)
{
Serial.print(inch, 2);
Serial.print('\t');
Serial.println(printInch(inch, 32));
}
Serial.println();
for (float feet = 0; feet < 100; feet += 5.43)
{
Serial.print(feet, 2);
Serial.print('\t');
Serial.println(printFeet(feet));
}
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,60 @@
Arduino UNO
IDE 1.8.19
print_performance.ino
PRINTHELPERS_VERSION: 0.4.1
4
4
Mass moon M = 7.34767309E+20
Speed of light c = 2.99792458E+8
Print E = Mc^2 = 6.6037592413026551656653076E+37
print64
TIME: 22476
660375892052148224
SCI
TIME: 9232
6.603759288787841E+17
ENG
TIME: 7388
660.375976562500000E+15
dtostrf
TIME: 2468
660375890000000000.000000000000000
dtostre
TIME: 1452
6.6037589e+17
toBytes
TIME: 1980
586.531 PB
hex
TIME: 1304
092A206000000000
bin
TIME: 2464
0000100100101010001000000110000000000000000000000000000000000000
toRoman
TIME: 89352
CMXCIX
printInch
TIME: 177308
999 0/16
printFeet
TIME: 137448
999"0'
done...

View File

@ -162,6 +162,36 @@ void setup()
Serial.println(b);
delay(100);
Serial.println();
Serial.println("printInch");
delay(100);
start = micros();
for (int i = 0; i < 1000; i++)
{
b = printInch(i);
}
stop = micros();
Serial.print("TIME: ");
Serial.println(stop - start);
Serial.println(b);
delay(100);
Serial.println();
Serial.println("printFeet");
delay(100);
start = micros();
for (int i = 0; i < 1000; i++)
{
b = printFeet(i);
}
stop = micros();
Serial.print("TIME: ");
Serial.println(stop - start);
Serial.println(b);
delay(100);
Serial.println();
Serial.println("done...");
}

View File

@ -67,6 +67,16 @@ void setup()
Serial.print("\t");
Serial.println(scieng(E, 8, em));
}
Serial.println();
if (sizeof(double) == 8)
{
while (E < 1e308)
{
E *= 1e5;
Serial.println(sci(E, 16));
}
}
Serial.println("\ndone...");
}

View File

@ -45,6 +45,14 @@ void setup()
Serial.println(b);
delay(1000);
// for (int i = 1; i <= 5000; i++)
// {
// Serial.print(i);
// Serial.print('\t');
// Serial.println(toRoman(i));
// }
// delay(1000);
Serial.println("\ndone...");
}

View File

@ -1,7 +1,7 @@
{
"name": "printHelpers",
"keywords": "Convert,int64,uint64,print,scientific,notation,toBytes,HEX,BIN,Roman",
"description": "Arduino library to help printing. int64 and uint64 support base 10 (DEC) and 16 (HEX). Scientific notation of floats.",
"description": "Arduino library to help printing. int64 and uint64 support base 10 (DEC) and 16 (HEX). Scientific notation of floats. Feet and inch.",
"authors":
[
{
@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/printHelpers"
},
"version": "0.4.0",
"version": "0.4.1",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,9 +1,9 @@
name=printHelpers
version=0.4.0
version=0.4.1
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library to help formatting data for printing. 64 bit integers (base 10 and 16). Engineering and scientific notation.
paragraph=Supports 64 bit integers (base 10 and 16). Engineering and scientific notation. toBytes() for KB MB, HEX and BIN, Roman numbers.
paragraph=Supports 64 bit integers (base 10 and 16). Engineering and scientific notation. toBytes() for KB MB, HEX and BIN, Roman numbers. Feet and inch.
category=Other
url=https://github.com/RobTillaart/printHelpers
architectures=*

View File

@ -2,7 +2,7 @@
// FILE: printHelpers.cpp
// AUTHOR: Rob Tillaart
// DATE: 2018-01-21
// VERSION: 0.4.0
// VERSION: 0.4.1
// PUPROSE: Arduino library to help formatting for printing.
// URL: https://github.com/RobTillaart/printHelpers
@ -258,9 +258,9 @@ char * sci(double value, uint8_t decimals)
}
void sci(Stream &str, double value, uint8_t decimals)
size_t sci(Stream &str, double value, uint8_t decimals)
{
str.print(sci(value, decimals));
return str.print(sci(value, decimals));
}
@ -277,7 +277,8 @@ void sci(Stream &str, double value, uint8_t decimals)
// so code wise difficult and as it is seldom used, support stops there.
//
// To have some support the code uses lowercase for the next 8 levels
// treda sorta rinta quexa pepta ocha nena minga luma (1024 ^21 ~~ 10^63)
// treda sorta rinta quexa pepta ocha nena minga luma (1024 ^13 ~~ 1024^21)
//
char * toBytes(double value, uint8_t decimals)
{
char * buffer = __printbuffer;
@ -417,7 +418,6 @@ char * bin(uint8_t value, uint8_t digits) { return bin((uint32_t) value, digits
//
// toRoman
//
// experimental
// extended with 10K units generated with the same but lower case chars.
// would expect a special char for 5000?
// need investigation.
@ -455,7 +455,7 @@ char * toRoman(uint32_t value)
idx++;
}
// set chars to lower
for (int i = 0; i < strlen(buffer); i++)
for (uint16_t i = 0; i < strlen(buffer); i++)
{
buffer[i] = tolower(buffer[i]);
}
@ -476,6 +476,61 @@ char * toRoman(uint32_t value)
}
////////////////////////////////////////////////////////////
//
// Distances
// Experimental
// step == 2,4,8,16,32,64,128,256 (default 16)
char * printInch(float inch, uint16_t step)
{
char * buffer = __printbuffer;
uint32_t whole = inch;
uint8_t num = round((inch - whole) * step);
if (num == step)
{
whole++;
num = 0;
}
uint8_t den = step;
// optional reduce
while ((num > 0) && ((num & 1) == 0))
{
num >>= 1;
den >>= 1;
}
#if defined(ESP32)
// ESP32 does not support %ld or ltoa()
sprintf(buffer, "%d %d/%d", whole, num, den);
#else
sprintf(buffer, "%ld %d/%d", whole, num, den);
#endif
return buffer;
}
char * printFeet(float feet)
{
char * buffer = __printbuffer;
uint32_t ft = feet;
uint8_t inch = round((feet - ft) * 12);
if (inch == 12)
{
ft++;
inch = 0;
}
#if defined(ESP32)
// ESP32 does not support %ld or ltoa()
sprintf(buffer, "%d\"%d\'", ft, inch);
#else
sprintf(buffer, "%d\"%d\'", ft, inch);
#endif
sprintf(buffer, "%d\"%d\'", ft, inch);
return buffer;
}
// -- END OF FILE --

View File

@ -3,7 +3,7 @@
// FILE: printHelpers.h
// AUTHOR: Rob Tillaart
// DATE: 2018-01-21
// VERSION: 0.4.0
// VERSION: 0.4.1
// PUPROSE: Arduino library to help formatting for printing.
// URL: https://github.com/RobTillaart/printHelpers
@ -12,7 +12,7 @@
#include "stdlib.h"
#define PRINTHELPERS_VERSION (F("0.4.0"))
#define PRINTHELPERS_VERSION (F("0.4.1"))
// global buffer used by all functions so no static buffer in every function
@ -55,7 +55,7 @@ char * eng(double value, uint8_t decimals); // em == 3
char * sci(double value, uint8_t decimals); // em == 1
void sci(Stream &str, double value, uint8_t decimals);
size_t sci(Stream &str, double value, uint8_t decimals);
////////////////////////////////////////////////////////////
@ -103,9 +103,19 @@ char * bin(uint8_t value, uint8_t digits = 8);
// toRoman()
//
// value should be in range 1..9999
// values 10K-100M are experimental (see readme.md)
// values 10K-100M are experimental in lower case (see readme.md)
char * toRoman(uint32_t value);
////////////////////////////////////////////////////////////
//
// Distances
// Experimental
//
// step == 2,4,8,16,32,64,128,256 (default 16)
char * printInch(float inch, uint16_t step = 16);
char * printFeet(float feet);
// -- END OF FILE --