Author Topic: Representing small values in C  (Read 5875 times)

0 Members and 1 Guest are viewing this topic.

Offline yashrkTopic starter

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: in
  • A MAKER, AN ENGINEER, A HOBBYIST FOR LIFE
    • My Personal Blog
Representing small values in C
« on: July 24, 2016, 04:26:39 pm »
Hello Guys,  :-+
              I have to represent and use small values like 1.40715e-09 in a calculation of a polynomial equation. I know I can use maths.h but I guess that will be more processor intensive, is there any better way of doing it ?
I have to solve this using dynamic values of x in each loop -
K = 1.40715e-09 * x^5 + 9.18189e-08 * x^4
I am using PIC18F4620 in MPLAB X.

Thanx.
Find me and things I'm working on - https://www.yashkudale.com/
 

Online T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 21685
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: Representing small values in C
« Reply #1 on: July 24, 2016, 04:29:03 pm »
If x and K are bounded integer ranges, it should suffice to use fixed point.

Otherwise, a floating point polynomial doesn't sound like the kind of thing you should need to compute on a PIC... find another solution?

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Representing small values in C
« Reply #2 on: July 24, 2016, 04:43:20 pm »
Code: [Select]
K = 1.40715e-09 * x^5 + 9.18189e-08 * x^4
rewrite it to:
Code: [Select]
K = a * (b * x + 1) * (c*x)^2^2

Find the appropriate a, b and c.
================================
https://dannyelectronics.wordpress.com/
 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: Representing small values in C
« Reply #3 on: July 24, 2016, 09:44:04 pm »
if you have enough space/not so many X values use a lookup table for the output otherwise you WILL have to use floating point math to keep a parvency of precision so unless you get a MCU with an FPU you will have to let it take its sweet time to calculate the value. a pic18 is much better than a pic16 in this case. a dspic is much better than a pic18 in this case. a pic32MZ EF is much better and so on
but i don't know your requiremenets, if the value has to be calculated on the fly all the timeor it is a sporadic measure etc
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: Representing small values in C
« Reply #4 on: July 25, 2016, 12:52:33 am »
Quote
K = 1.40715e-09 * x^5 + 9.18189e-08 * x^4
What is the range of "x"?  What is the expected range of the result?  What is the required accuracy of the result?
If you have floating point involved anyway, then using "small" values as you've shown should not cause any additional problems (though it is probably desirable to avoid floating point entirely, if you can.)  (although, with REALLY small numbers (Planck's constant squared, my memory says - a very educational experience, that assignment...), you can exceed the limits of some floating point formats...)

 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11634
  • Country: my
  • reassessing directives...
Re: Representing small values in C
« Reply #5 on: July 25, 2016, 12:59:21 am »
without giving much clue of how many bit resolution required, the answer can be anything. for eg, is x integer? whats the min max value of x?
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline yashrkTopic starter

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: in
  • A MAKER, AN ENGINEER, A HOBBYIST FOR LIFE
    • My Personal Blog
Re: Representing small values in C
« Reply #6 on: July 25, 2016, 01:46:15 am »
X is an 22 bit ADC value which is always positive
Find me and things I'm working on - https://www.yashkudale.com/
 

Offline yashrkTopic starter

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: in
  • A MAKER, AN ENGINEER, A HOBBYIST FOR LIFE
    • My Personal Blog
Re: Representing small values in C
« Reply #7 on: July 25, 2016, 01:52:46 am »
And yes the value has to be calculated at least ones in every time it goes through the "main"  loop, so I do want it as fast as possible and for the accuracy I need it to be accurate till 2-3 decimal places
Find me and things I'm working on - https://www.yashkudale.com/
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11634
  • Country: my
  • reassessing directives...
Re: Representing small values in C
« Reply #8 on: July 25, 2016, 02:56:16 am »
thats complicated, you'll need to track exponent from -9 to 24, probably need to device for mantissa storage/tracking as well. you'll probably will end up as slow as fp op. bed time here others may help, good luck.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2548
  • Country: us
Re: Representing small values in C
« Reply #9 on: July 25, 2016, 03:05:36 am »
How fast do you need to sample the DAC and what else does the PIC need to do?

If you have lots of time, just use doubles and do the calculation.  Normal software development is to code it the most straight forward way and then optimize it if you need to reduce memory size or decrease the computation time.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26906
  • Country: nl
    • NCT Developments
Re: Representing small values in C
« Reply #10 on: July 25, 2016, 07:36:13 am »
How fast do you need to sample the DAC and what else does the PIC need to do?

If you have lots of time, just use doubles and do the calculation.  Normal software development is to code it the most straight forward way and then optimize it if you need to reduce memory size or decrease the computation time.
Very true! I assume there is a soft floating point library for PIC as well so start using that and see if it is fast enough. Also using a faster processor (ARM) may be a lot easier than trying to squeeze performance out of a slow 8 bit processor.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline dmills

  • Super Contributor
  • ***
  • Posts: 2093
  • Country: gb
Re: Representing small values in C
« Reply #11 on: July 25, 2016, 03:07:18 pm »
Small PIC floating point libs are sometimes very much NOT IEEE754, so be sure to read the documentation......


Regards, Dan.
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: Representing small values in C
« Reply #12 on: July 25, 2016, 03:54:20 pm »
Depending of the precision required, performing the arithmetics using logarithms and performing the need conversions using lookup-tables may also be an option. Googling using the following magic keywords may give some ideas: floating point arithmetic using logarithms
 

Offline MosherIV

  • Super Contributor
  • ***
  • Posts: 1530
  • Country: gb
Re: Representing small values in C
« Reply #13 on: July 25, 2016, 04:07:02 pm »
Assuming the number of fractional bits stay the same between calculations, have you looked at how DSPs handle floating point numbers?

https://en.wikipedia.org/wiki/Q_%28number_format%29
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Representing small values in C
« Reply #14 on: July 25, 2016, 08:59:51 pm »
Are you calculating K given an 'x' value, or , or solving for x, when K is known?

Anyhow... this might be better

Code: [Select]
28428252164 * K = (4*x^5 + 261*x^4)
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline helius

  • Super Contributor
  • ***
  • Posts: 3642
  • Country: us
Re: Representing small values in C
« Reply #15 on: July 25, 2016, 09:13:45 pm »
Are we really talking about the C language here? I see a whole bunch of code snippets that use ^ for exponentiation. Really?
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2548
  • Country: us
Re: Representing small values in C
« Reply #16 on: July 25, 2016, 09:46:43 pm »
Are we really talking about the C language here? I see a whole bunch of code snippets that use ^ for exponentiation. Really?

Ya.  That's the notation in C.  Get use to it.
 

Offline Len

  • Frequent Contributor
  • **
  • Posts: 547
  • Country: ca
Re: Representing small values in C
« Reply #17 on: July 25, 2016, 10:07:30 pm »
Are we really talking about the C language here? I see a whole bunch of code snippets that use ^ for exponentiation. Really?

Ya.  That's the notation in C.  Get use to it.

No it isn't. ^ is the binary xor operator in C.

yashrk wasn't writing C code. He wrote a mathematical formula and asked how it should be calculated in C.
DIY Eurorack Synth: https://lenp.net/synth/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Representing small values in C
« Reply #18 on: July 25, 2016, 10:16:53 pm »
"Anyhow... this might be better"

Using x4 to calculate x5.
================================
https://dannyelectronics.wordpress.com/
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Representing small values in C
« Reply #19 on: July 25, 2016, 10:40:04 pm »
If he the OP really wants to calculate this efficiently on a low end part the best way would be to normalize everything into a custom floating point format (i.e. a 32 bit number representing 0.5000 (0x80000000 to 0xFFFFFFFF) and an exponent (maybe from 2^-32768 to 2^32768).

Write a routine to normalize the numbers...

Code: [Select]
void normalize(u32 *mantissa, u16 *exponent) {
  if(*mantissa == 0) {
     *exponent = 0;
     return;
  }
  while(*mantissa & 0xC0000000 != 0) {
     *mantissa<<=1;
     *exponent--;
  }

Then multiplications become

Code: [Select]
void multiply(u32 *mantissa_1, u16 *exponent_1, u32 *mantissa_1, u16 *exponent_1) {
    *mantissa_1 = (u32)(((u64)(*mantissa_1) * (u64)*mantissa_2)>>32);
    *exponent_1 = *exponent_1 + *exponent_2;
    normalize(&mantissa_1, &exponent_1);
}

Addition is a bit trickier, as you have to put things to a common exponent (whichever is the highest) and then add, and allow for an overflow.

With that infrastructure the calculation becomes:

Code: [Select]
void calc(m_x, e_x) {

  *m_temp1 = *m_x;
  *e_temp1  = *e_x;  /* temp_1 = x */

  multiply(&m_temp1, &e_temp1, &m_x,& e_x);   /* temp_1 = x^2 */
  multiply(&m_temp1, &e_temp1, &m_x,& e_x);   /* temp_1 = x^3 */
  multiply(&m_temp1, &e_temp1, &m_x,& e_x);   /* temp_1 = x^4 */

  *m_temp2 = *m_temp1;  /* temp2 = x^4 */
  *e_temp2 = *e_temp1;

  multiply(&m_temp1, &e_temp1, &m_x,& e_x);   /* temp_1 = x^5 */

  multiply(&m_temp1, &e_temp1, &m_const1, e_const1); /* temp1 = const1 * x^5 */
  multiply(&m_temp2, &e_temp2, &m_const2, e_const2); /* temp1 = const2 * x^4*/

  add((&m_temp1, &e_temp1, &m_temp2, &e_temp2);  /* temp1 = const1 * x^5  +  const2 * x^4 */

  /* K is now in m_temp1 & e_temp1 */
}
« Last Edit: July 25, 2016, 10:59:05 pm by hamster_nz »
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Representing small values in C
« Reply #20 on: July 25, 2016, 11:55:12 pm »
This is easy:

produce a complete compilable routine that converts a 22-bit adc to a floating point output, as per the OP's formula, with the fastest execution and/or smallest space.

Go!
================================
https://dannyelectronics.wordpress.com/
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2548
  • Country: us
Re: Representing small values in C
« Reply #21 on: July 26, 2016, 12:35:20 am »
Are we really talking about the C language here? I see a whole bunch of code snippets that use ^ for exponentiation. Really?

Ya.  That's the notation in C.  Get use to it.

No it isn't. ^ is the binary xor operator in C.

yashrk wasn't writing C code. He wrote a mathematical formula and asked how it should be calculated in C.

You're right.  Don't know what I was thinking.   :palm:
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2548
  • Country: us
Re: Representing small values in C
« Reply #22 on: July 26, 2016, 12:39:05 am »
If he the OP really wants to calculate this efficiently on a low end part the best way would be to normalize everything into a custom floating point format (i.e. a 32 bit number representing 0.5000 (0x80000000 to 0xFFFFFFFF) and an exponent (maybe from 2^-32768 to 2^32768).

Write a routine to normalize the numbers...

Test... Test... Test...
Many times the compiler will out smart you and it will actually take longer to execute with the optimization.
I've seen it very often.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: Representing small values in C
« Reply #23 on: July 26, 2016, 12:41:21 am »
Quote
X is an 22 bit ADC value which is always positive
Sigh.  A 22bit raw ADC-reading number like "1000000", or an analog voltage value derived from that like "((1000000 * Vref)/4194304.0)" ?
Thermocouple? (link to datasheet?)  Expected temperature range or analog voltage range?  (22bit ADC, eh?  Damn!)

but don't most of those high-res ADC have conversion times in the ms to 200ms range?  Are you sure you need "fast" ?
start with some simple optimization like:
Code: [Select]
x4 = x*x*x*x;
K = x4*(1.40715e-9 *x + 9.18189e-8);
and see if it is "fast enough" (premature optimization is the root of much evil.)
(normally, I'd hope that a compiler would produce equivalent code from a straightforward expression like "K = 1.4e-9*pow(x,4) + 9.2e-8*pow(x,5)", but ... I'm not sure, I especially don't trust the 8bit PIC compilers, and x*x*x*x is probably faster than pow(x,4) anyway.)

(edited: replace embarrassing misuse of "exp" function with correct "pow" function.)
« Last Edit: July 26, 2016, 06:54:51 am by westfw »
 

Offline helius

  • Super Contributor
  • ***
  • Posts: 3642
  • Country: us
Re: Representing small values in C
« Reply #24 on: July 26, 2016, 02:00:00 am »
and x*x*x*x is probably faster than exp(x,4) anyway.)
exp(x) computes \$e^x\$. pow(x,y) is defined to return a double, anyway.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf