From 1d60979740807cf03260730e7f5e46ebaecd191a Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Thu, 21 Nov 2024 13:48:53 +0100 Subject: [PATCH] fix #22, sign of fractions + roman --- CHANGELOG.md | 8 ++++++ README.md | 32 +++++++++++++++------ examples/print_toRoman/print_toRoman.ino | 11 +++++++- library.json | 2 +- library.properties | 2 +- printHelpers.cpp | 36 ++++++++++++++---------- printHelpers.h | 4 +-- test/unit_test_001.cpp | 26 ++++++++++++++++- 8 files changed, 92 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd15bf5..8476d36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.4.6] - 2024-11-21 +- fix #22, negative fractions +- fix unofficial **toRoman()** for > 4888 +- add support for negative sign for **toRoman()** +- changed parameter to signed **toRoman(int32_t value)** +- add unit tests +- update readme.md + ## [0.4.5] - 2024-11-20 - add experimental **fraction()** - add **print_fractions.ino** example diff --git a/README.md b/README.md index 19e7f1b..12584ea 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ data in a way not supported in the standard print library of the Arduino. - **char \* toBytes()** returns a string in KB MB GB etc. - **char \* hex()** returns hexadecimal output with **leading zeros** up to **uint64_t**. - **char \* bin()** returns binary output with **leading zeros** up to **uint64_t**. -- **char \* toRoman()** returns a ROMAN representation of a (positive) number. +- **char \* toRoman()** returns a ROMAN representation of a number. - **char \* printInch(float inch, uint16_t step)** returns a string e.g. 5 7/8". - **char \* printFeet(float feet)** returns a string e.g. 7"4' - **char \* csi()** returns a comma separated integer for readability e.g. 3,254,152. @@ -137,7 +137,9 @@ These will all be shown in UPPERCASE so KB, MB etc. | exabytes | EB | 1024^6 | udabytes | UB | 1024^12 | -Treda Byte is shortened as "TDB" and uses 2 chars to indicate the magnitude. +#### Bigger + +Treda Byte is officially shortened as "TDB" and uses 2 chars to indicate the magnitude. That would take extra memory or slightly more complex code. As it is very seldom used, "official" support stops with UDA. Should be big enough for some time. @@ -145,9 +147,23 @@ 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\^13 ~~ 1024\^21) To enable this patch the function in the **printHelpers.cpp** file. +| Unit | abbrev. | size | +|:-----------:|:---------:|:---------:| +| tredabytes | tB | 1024^13 | +| sortabytes | sB | 1024^14 | +| rintabytes | rB | 1024^15 | +| quexabytes | qB | 1024^16 | +| peptabytes | pB | 1024^17 | +| ochabytes | oB | 1024^18 | +| nenabytes | nB | 1024^19 | +| mingabytes | mB | 1024^20 | +| lumabytes | lB | 1024^21 | + +Note that from the ZETTA prefix all higher prefixes are starting with the +previous letter of the alphabet ZYXWVUtsrqponml + ### hex() bin() @@ -186,7 +202,7 @@ A less used but well known print format are the Roman digits. The library function **toRoman()** will convert any number from 0..100 million into a Roman number. The numbers 1..5000 ("official" range) are the well known UPPER case characters. -- **char \* toRoman(uint32_t value)** returns Roman string. +- **char \* toRoman(int32_t value)** returns Roman string. | char | unit | notes | |:------:|:-------|:------------| @@ -205,7 +221,6 @@ Note: The maximum length returned is 16 characters in the "official" supported r Notes: - value == 0 => N is not part of the "official" numbers but we need it. -- values < 0 are not supported (note parameter is unsigned) - values between 5K-10K are extended with extra M chars. - values 10K-100M are represented with lower case characters. This is not a standard, but it sort of works well. @@ -216,6 +231,8 @@ Notes: 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. +Since 0.4.6 negative numbers will have a - sign in front. + ### Distance feet inch @@ -314,12 +331,13 @@ When functions are added, the recommended minimum size might increase. #### Must - check TODO's in the code +- documentation #### Should -- documentation - improve readability of the code - em ==> exponentFactor? +- extend unit tests #### Could @@ -332,8 +350,6 @@ When functions are added, the recommended minimum size might increase. - pass char buffer as parameter (breaking) - could be the log10 pow version? - optimize **char \* hex(uint8_t / uint16_t ...)** -- negative ROMAN numbers (add a - sign) - #### Wont diff --git a/examples/print_toRoman/print_toRoman.ino b/examples/print_toRoman/print_toRoman.ino index e0ef821..7de79f3 100644 --- a/examples/print_toRoman/print_toRoman.ino +++ b/examples/print_toRoman/print_toRoman.ino @@ -49,7 +49,16 @@ void setup() stop = micros(); Serial.println((stop - start) / 5000.0); Serial.println(b); - delay(1000); + delay(100); + + // unofficial romans + start = micros(); + b = toRoman(12345678); + stop = micros(); + Serial.println(); + Serial.println(stop - start); + Serial.println(b); + delay(100); // for (int i = 1; i <= 5000; i++) // { diff --git a/library.json b/library.json index 54cdd59..b388f29 100644 --- a/library.json +++ b/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/printHelpers" }, - "version": "0.4.5", + "version": "0.4.6", "license": "MIT", "frameworks": "*", "platforms": "*", diff --git a/library.properties b/library.properties index b6ea908..623eb35 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=printHelpers -version=0.4.5 +version=0.4.6 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library to help formatting data for printing. 64 bit integers (base 10 and 16). Engineering and scientific notation. diff --git a/printHelpers.cpp b/printHelpers.cpp index beefbac..bcbbf9e 100644 --- a/printHelpers.cpp +++ b/printHelpers.cpp @@ -2,7 +2,7 @@ // FILE: printHelpers.cpp // AUTHOR: Rob Tillaart // DATE: 2018-01-21 -// VERSION: 0.4.5 +// VERSION: 0.4.6 // PURPOSE: Arduino library to help formatting for printing. // URL: https://github.com/RobTillaart/printHelpers @@ -421,36 +421,41 @@ char * bin(uint8_t value, uint8_t digits) { return bin((uint32_t) value, digits // extended with 10K units generated with the same but lower case chars. // would expect a special char for 5000? // need investigation. -char * toRoman(uint32_t value) +char * toRoman(int32_t value) { - char * buffer = __printbuffer; - uint32_t val = value; + char * buffer = __printbuffer; + int32_t val = value; uint16_t n[13] = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; char roman[13][3] = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" }; buffer[0] = 0; int idx = 0; - if (value == 0) + if (val == 0) { strcat(buffer, "N"); // NULL return buffer; } - - if (value > 100000000UL) + // handle negative values + if (val < 0) + { + strcat(buffer, "-"); + val = -val; + } + if (val > 100000000L) { strcat(buffer, "OVF"); // overflow return buffer; } - if (val >= 10000UL) + if (val >= 10000L) { // 10K units - while(val >= 10000UL) + while(val >= 10000L) { - while (val >= (10000UL * n[idx])) + while (val >= (10000L * n[idx])) { strcat(buffer, roman[idx]); - val -= (10000UL * n[idx]); + val -= (10000L * n[idx]); }; idx++; } @@ -460,7 +465,8 @@ char * toRoman(uint32_t value) buffer[i] = tolower(buffer[i]); } } - + // reset index + idx = 0; // Official part UPPER case letters while(val > 0) { @@ -776,16 +782,16 @@ char * fraction(double value) // ESP32 does not support %ld or ltoa() sprintf(buffer, "-%d/%d", highN, highD); #else - sprintf(buffer, "%ld/%ld", highN, highD); + sprintf(buffer, "-%ld/%ld", highN, highD); #endif } else { #if defined(ESP32) // ESP32 does not support %ld or ltoa() - sprintf(buffer, "-%d/%d", highN, highD); + sprintf(buffer, "%d/%d", highN, highD); #else - sprintf(buffer, "-%ld/%ld", highN, highD); + sprintf(buffer, "%ld/%ld", highN, highD); #endif } return buffer; diff --git a/printHelpers.h b/printHelpers.h index 0011838..988c3f2 100644 --- a/printHelpers.h +++ b/printHelpers.h @@ -3,7 +3,7 @@ // FILE: printHelpers.h // AUTHOR: Rob Tillaart // DATE: 2018-01-21 -// VERSION: 0.4.5 +// VERSION: 0.4.6 // PURPOSE: Arduino library to help formatting for printing. // URL: https://github.com/RobTillaart/printHelpers @@ -106,7 +106,7 @@ char * bin(uint8_t value, uint8_t digits = 8); // // value should be in range 1..9999 // values 10K-100M are experimental in lower case (see readme.md) -char * toRoman(uint32_t value); +char * toRoman(int32_t value); //////////////////////////////////////////////////////////// diff --git a/test/unit_test_001.cpp b/test/unit_test_001.cpp index 48f1451..273922b 100644 --- a/test/unit_test_001.cpp +++ b/test/unit_test_001.cpp @@ -161,8 +161,32 @@ unittest(test_toRoman_standard) unittest(test_toRoman_extended) { + // zero test assertEqual(0, strcmp("N", toRoman(0)) ); - assertEqual(0, strcmp("OVF", toRoman(100000001UL)) ); + // overflow + assertEqual(0, strcmp("OVF", toRoman(100000001L)) ); + assertEqual(0, strcmp("-OVF", toRoman(-100000001L)) ); + // negative + assertEqual(0, strcmp("-MCCXXXIV", toRoman(-1234))); + + // large + assertEqual(0, strcmp("cxxiiiMMMMDLXVII", toRoman(1234567))); +} + + +unittest(test_fraction) +{ + // positive + assertEqual(0, strcmp("59/469", fraction(0.1258)) ); + + // zero + assertEqual(0, strcmp("0/1", fraction(0)) ); + + // negative + assertEqual(0, strcmp("-59/469", fraction(-0.1258)) ); + + // fixed denumerator + assertEqual(0, strcmp("1/8", fraction(0.1258, 8)) ); }