Global Moderator
Netherlands
Offline
Shannon Member
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...


« Reply #60 on: September 01, 2013, 03:29:11 am » 
new patch ... (code increase) case ENG: case SCI: n += write('E'); if (exponent >= 0) n += write('+'); else { exponent = exponent; n += write(''); } if (exponent < 10) n += write('0'); n += print(exponent); break;



Logged





Rapa Nui
Offline
Edison Member
Karma: 52
Posts: 1990
Pukao hats cleaning services


« Reply #61 on: September 01, 2013, 04:00:56 am » 
PS: my above replay on rounding: it shall be applicable for SCI as well I think. So always take for the rounding "reference" the digit right to the digit which will be printed last.
0.234293 SCI,3: 2.343E01 ENG,4: 234.3E3 SI,4: 234.3m


« Last Edit: September 01, 2013, 04:08:28 am by pito »

Logged





Global Moderator
Netherlands
Offline
Shannon Member
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...


« Reply #62 on: September 01, 2013, 04:06:20 am » 
The rounding code is still based upon #decimals iso #total digits. And with the ENG notation the rounding factor depends indeed on the value of the last printed digit. But you have to determine that before printing.
Needs some thinking to make it robust for all 4 formats (first step is a notation dependent rounding and merge later)


« Last Edit: September 01, 2013, 06:09:12 am by robtillaart »

Logged





Rapa Nui
Offline
Edison Member
Karma: 52
Posts: 1990
Pukao hats cleaning services


« Reply #63 on: September 01, 2013, 04:16:47 am » 
For "number of digits" based formats (SCI/ENG/SI) the rule is following:
The reference for rounding is the digit right to the digit to be printed last.
So when printing with 4 digits, start with 4+1= 5 digits, make rounding based on the 5th digit, and then work with the first 4 digits as usual.


« Last Edit: September 01, 2013, 04:26:20 am by pito »

Logged





Global Moderator
Netherlands
Offline
Shannon Member
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...


« Reply #64 on: September 01, 2013, 06:08:53 am » 
That's ok but one moment the 5th digit is O(E1) the other time it is O(E2) or O(E3)
special test case is print(999.99, 4, ENG); which becomes 1000.0E+00 (wrong) or 1.000E+03 (right) That's why determination of the exponent should be done after rounding, but to determine the rounding factor you need to know the exponent.


« Last Edit: September 01, 2013, 06:16:01 am by robtillaart »

Logged





U.K
Offline
Jr. Member
Karma: 1
Posts: 70


« Reply #65 on: September 01, 2013, 06:38:24 am » 
back with my changes to print.cpp to account for the actual ( real accurate digits the number can hold ) when in SCI / ENG mode, this should apply to the rounding you are seeing here ?
ie. if the data doesn't hold a value worth rounding then dont do it maybe ?


« Last Edit: September 09, 2013, 04:51:11 pm by darryl »

Logged

 Darryl




Rapa Nui
Offline
Edison Member
Karma: 52
Posts: 1990
Pukao hats cleaning services


« Reply #66 on: September 01, 2013, 07:54:15 am » 
That's ok but one moment the 5th digit is O(E1) the other time it is O(E2) or O(E3) I did not study the code, but I would expect you go from raw mantissa (significand  there are all the digits available ), for ndigitsprecision take first n+1, round, go back to n and so on. You do not need exponent to know for messing with digits, I think.. For 4 digits precision: m: 999999 exp: x take first 4+1 digits and round m: 99999+5 exp:x m: 100004 and if 1st digit went from 9>1 x=x+1 take first 4 digits m: 1000 exp: x+1 do conversion to ENG/SI


« Last Edit: September 01, 2013, 08:22:13 am by pito »

Logged





Global Moderator
Netherlands
Offline
Shannon Member
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...


« Reply #67 on: September 01, 2013, 08:03:50 am » 
new BETA version of my print.cpp/.h
+ rounding SCI/ENG/SI

Print.cpp (19.86 KB  downloaded 25 times.)
Print.h (3.03 KB  downloaded 20 times.)


Logged





Global Moderator
Netherlands
Offline
Shannon Member
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...


« Reply #68 on: September 01, 2013, 09:03:50 am » 
That's ok but one moment the 5th digit is O(E1) the other time it is O(E2) or O(E3) I did not study the code, but I would expect you go from raw mantissa (significand  there are all the digits available ), for ndigitsprecision take first n+1, round, go back to n and so on. You do not need exponent to know for messing with digits, I think.. For 4 digits precision: m: 999999 exp: x take first 4+1 digits and round m: 99999+5 exp:x m: 100004 and if 1st digit went from 9>1 x=x+1 take first 4 digits m: 1000 exp: x+1 do conversion to ENG/SI  The raw mantissa is not a decimal value. It is binary, and the exponent is binary too (google IEEE754 wikipedia)  To change the first n digits of a float into an integer value I need to multiply the float by some number. To find that number is (almost) equivalent to finding the exponent. I did not study the code, please do ...



Logged





Peoples Republic of Cantabrigia
Offline
God Member
Karma: 6
Posts: 691
Arduino happiness


« Reply #69 on: September 04, 2013, 09:57:17 am » 
Hi Rob,
Thanks for your updates to print, I have been using bignumbers as a substitute.
Just wondering, is your fix going to become part of the default IDE?
Also, how hard would it be to implement longer 'standard' numbers in the IDE? I am interested in int128, for example. For that matter, it would be great if double was in fact a double float...



Logged





Global Moderator
Netherlands
Offline
Shannon Member
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...


« Reply #70 on: September 04, 2013, 12:39:17 pm » 
Hi Rob,
Thanks for your updates to print, I have been using bignumbers as a substitute.
Just wondering, is your fix going to become part of the default IDE?
Also, how hard would it be to implement longer 'standard' numbers in the IDE? I am interested in int128, for example. For that matter, it would be great if double was in fact a double float...
First the fixes/ideas here are not only mine as more people cooperated to get this far. I do not expect it to become part of the default IDE soon as imho it is not tested enough yet. Furthermore there are two main features in it: faster printing and printing SCI/ENG/SI format.  The first has currently assembly in it, very fast but not portable to e.g. the DUE,  The SCI/ENG/SI formatting works only for floats at the moment. Maybe 3 extra formats is too much.  Support for printing long long; // maybe most stable part On the positive site the lib is backwards compatible so it can be used by the ones who want to. Finally Paul Stoffregen, Designer of the Teensy  http://www.pjrc.com/teensy/index.html , will incorporate the work in a coming (not perse next) release. Mentioned above somewhere. Implementing an IEEE754(?) 64bit double in the IDE is not trivial and would take quite some time. Implementing a proprietary larger float is simpler, one can make a class that uses for example Class Ardouble {
private: bool s; // sign, true => negative; unsigned long m; // 32 bits mantisse => 9 significant digits iso 32bit float 23 bits mantissse which has 67 significant digits. int exponent; // use power of 10 => 32767 .. +32767 (OK maybe a byte is enough ;) }; Then you need to implement a math library and conversion from and to existing base types (at least float), not very difficult but not trivial either. quite some work. Start with +* /% and boolean operators like < > == and != If that works then continue with functions like sin() cos() exp() ln() pow() sqrt() trunc() floor() ceil() etc. Implementing an int128 class is probably easier but it will be very slow. Have you ever worked with the LONG LONG ?



Logged





Peoples Republic of Cantabrigia
Offline
God Member
Karma: 6
Posts: 691
Arduino happiness


« Reply #71 on: September 04, 2013, 02:44:15 pm » 
Hi Rob,
Yeah, I saw the assembly code and my heart sank  can't use it in the Teensy! However, I am psyched to hear that Paul may be incorporating it into the Teensy IDE... makes sense too given how many bits a 32bit processor can handle/accumulate/etc.
As for double, I am curious why it was implemented at all if it simply defaults to float precision. I would have simply left it out.
And yes, I worked with long long until I hit a wall of sorts... one of my projects involved a least squares solver for 16 Bit ADC error minimization. Worked like a charm in Excel but numbers with 25 digits couldn't be handled by a 2^64 capable variable (i.e. can't handle anything bigger than 1.84e+19). Hence the use of the BigNumbers library (Thank you, Mr. Gammon!).
Given my knowledge re: libraries, etc. I'll simply continue using BigNumbers then for these sorts of jobs. All the more advisable since Mr. Gammon and Stoffregen have implemented BigNumbers on the Teensy as well.



Logged





Global Moderator
Netherlands
Offline
Shannon Member
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...


« Reply #72 on: September 05, 2013, 09:57:03 am » 
As for double, I am curious why it was implemented at all if it simply defaults to float precision. I would have simply left it out. I think it is mandatory to implement double to keep the compiler happy, and that the implementation is platform dependent.



Logged





U.K
Offline
Jr. Member
Karma: 1
Posts: 70


« Reply #73 on: September 09, 2013, 04:57:57 pm » 
going on from my changes to printNumber ( in print.cpp ) where I suggested an extra parameter to being the leading zeroes ( positive for x number of them, 0 or negative to print none ) it also gains a nice addition of printing HEX and BIN numbers for free. size_t Print::printNumber(uint32_t num, uint8_t base, uint8_t leading_zeros) { char buf[33]; // Assumes 8bit chars plus zero byte. was > "8 * sizeof(int32_t) + 1" char *str = &buf[sizeof(buf)  1]; *str = '\0'; ...... int8_t extra_digits = leading_zeros;
...... ...... ......
// have we got some leading zero's to also print ? for ( ; extra_digits > 0; extra_digits ) *str = '0';
return write(str); }
and then in print.h class Print { private: ...... size_t printNumber(uint32_t, uint8_t, uint8_t);
public: ...... ...... size_t print(uint8_t num, uint8_t base) { return (base == HEX) ? printNumber(num, HEX, 2) : (base == BIN) ? printNumber(num, BIN, 8) : printNumber(num, base, NO_LEADING_ZERO); } size_t print(int16_t num, uint8_t base) { return print((int32_t)num, base); } size_t print(uint16_t num, uint8_t base) { return (base == HEX) ? printNumber(num, HEX, 4) : (base == BIN) ? printNumber(num, BIN, 16) : printNumber(num, base, NO_LEADING_ZERO); } size_t print(int32_t num, uint8_t base) { return (base == DEC) ? print(num) : printNumber(num, base, NO_LEADING_ZERO); } size_t print(uint32_t num, uint8_t base) { return (base == HEX) ? printNumber(num, HEX, 8) : (base == BIN) ? printNumber(num, BIN, 32) : printNumber(num, base, NO_LEADING_ZERO); } ...... ......
lots of code missed by the "....." but the listed codes gives the idear of what to patch / add. Rob, your suggested way of adding the leading zeroes ( when doing the decimal part of output of course needs to be changed to the way I had used, but its useful for the freebie gain on HEX and BIN output I think. would fix this call as well https://github.com/arduino/Arduino/issues/1097



Logged

 Darryl




Offline
Newbie
Karma: 0
Posts: 16


« Reply #74 on: December 24, 2013, 08:02:09 am » 
darryl, if I'm reading your code right you're changing the behaviour of Print.print(1, HEX) to output "01" instead of "1", right? I don't expect that change to be ever accepted into the Arduino codebase  doing so causes sketches that rely on the old behaviour (for example because they print the leading zero manually) to break.
To do this properly, I think the leading zero printing must be made optional, defaulting to not printing them. An easy way is to just add a "min_digits" argument to the print functions, which defaults to 0?



Logged





