Welcome to the Parallax Discussion Forums, sign-up to participate.

Forum Update - Announcement about May 10th, 2018 update and your password.

todieforteo
Posts: **7**

Hi everyone,

I have a quicstart board. I am using double and float variable for meter calculating, but when I use float variable , it is get max value 5242,00. Then I use double variable it is get max value 8192,00. I know this is not the maximum value of these variables. I want to calculate higher meter values.

Please help me.

Thanks in advance.

I have a quicstart board. I am using double and float variable for meter calculating, but when I use float variable , it is get max value 5242,00. Then I use double variable it is get max value 8192,00. I know this is not the maximum value of these variables. I want to calculate higher meter values.

Please help me.

Thanks in advance.

## Comments

21 Commentssorted by Date Added Votes1,1500Vote UpVote Down70Vote UpVote Down1,1500Vote UpVote DownTo get some more precision, try using fixed-point arithmetic: use 32-bit ints for metre1 and pulse_distance, and set pulse_distance = 1. When you interpret the value of metre1, remember that the stored value is the true value divided by 0.000305: you need to multiply it by 0.000305 before displaying it. You can do this last multiplication using floats if you're lazy, but there are ways to do it without any floats.

4,8830Vote UpVote DownAs Electrodude says, a Single's more limited mantissa is getting in the way. You need about 34 bits but a Single only provides 24 bits. How it will be working is it'll start off accumulating correctly but as you exceed the 24-bit capacity the lowest bits get rounded off and the new additions will also be rounded, maybe truncated. Result is rubbish.

4,8830Vote UpVote DownAside from that detail, what result were you expecting? 1000.00 presumably.

The hard coded 305 micron preset for the encoder pulse increments looks suspiciously like the number of millimetres in a foot rather than something suited to a metre.

3370Vote UpVote DownYou'll have to multiply your entire system by 10^6, but just for the setup. Once it's running the math is the same only with whole numbers.

Since you are only printing 2 decimal digits:

1) Print all but the last 6 digits

2) Print a decimal

3) Print the the two "decimal" digits

Your print will be slower, but your math will be faster and you will experience no rounding errors.

Your max range will be 18,446,744,000,000

Floating point numbers will be our downfall; count on it.

Imagine a world without hypothetical situations.

4,8830Vote UpVote DownIf this was applied to an integer the adder circuits will roll over back to zero and carry on. It's clear when a roll over occurs and needs more bits. With floats it's not so clear you've hit the precision limit. The errors just grow until it stops accumulating altogether.

To summarise, floating-point doesn't suit this application, fixed-point (Integers) is the better choice.

Only after the data is captured should you be processing into floats for display/analysis.

3370Vote UpVote DownThis compiles just fine. Think I got it all. There was an errant variable sayac that I commented out.

Floating point numbers will be our downfall; count on it.

Imagine a world without hypothetical situations.

20,7520Vote UpVote DownThat does not work. You have metre1 as type uint64_t. That means it can not be negative. The "metre1 -= pulse_distance;" will underflow!

Personally I would just count the pulses up and down in steps of 1. No point in wasting bits by incrementing/decrementing by anything bigger than 1.

When you want to use that count as a distance in meters multiply it by the appropriate scaling factor.

Better still. Don't use floats or doubles. Use fixed point arithmetic. Everything can be done using integers scaled up by an appropriate power of 2.

4,8830Vote UpVote DownIt'll work fine because there isn't any attention paid to the arithmetic flags in the ALU. The 2's-complement circuit works the same with signed and unsigned. There'll probably be a compile time warning, but no ill effects.

Your increment by one is ideal solution though.

EDIT: Typo

20,7520Vote UpVote DownConsider the following code:

Which outputs:

0.000305

5626256833904640.000000

Changing count to int64_t produce the right result.

There are no warning from the compiler in either case.

4,8830Vote UpVote Down20,7520Vote UpVote DownYou might have to explain that one.

4,8830Vote UpVote Down20,7520Vote UpVote DownCertainly the C language defines what should happen when unsigned ints overflow or underflow.

On the other hand overflow of signed integers is undefined behavior in C. Anything could happen and it would all be C compliant.

But, even if that unsigned underflow I show above is defined behavior and legitimate C code, the code as a whole is not doing what we want. It's wrong, a bug.

3,0580Vote UpVote DownActually it doesn't. C follows the usual CPU convention of being agnostic as to whether ints are signed or unsigned for addition and subtraction, so those operations are "circular." Whether MSB set means negative or bigger is determined by how you print it out and how you do other operations like multiply and divide. The actual addition and subtraction operations are the same and roll over. Confusion on this point is why 32-bit systems are often considered to be limited to 2 gigabytes instead of 4 -- much code invisibly uses signed math for multiplication, causing errors in the calculation of addresses with MSB set.

3370Vote UpVote DownI do not know all the definitions. Can you please recommend a pdf on the topic?

I have not replied yet because I feared that I had made a mistake. So I tested it. Regardless of the definitions, Heater was correct on two points:

1) The underflow that I was counting on failed and an int64_t is the correct choice

2) I should have made the logical jump to incrementing and decrementing by 1 as it allows for the maximum range and any adjustments can be made right before printing as that only happens once

So same code basically, just make it an int64_t, increment by 1, cast double and multiply the result by 305/10^6

Did I understand the fix correctly @heater?

Floating point numbers will be our downfall; count on it.

Imagine a world without hypothetical situations.

20,7520Vote UpVote Downhttps://www.iso.org/standard/57853.html

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf

https://isocpp.org/std/the-standard

Contrary to what localroger says, wraparound behavior using unsigned integers is legal and well-defined, and there are code idioms that deliberately use it. On the other hand, C and C++ have undefined semantics for signed overflow and shift past bitwidth.

The above phrasing shamelessly borrowed from this great document on the subject:

https://www.cs.utah.edu/~regehr/papers/overflow12.pdf

As localroger says, there is confusion on this point.

Sounds like you have the hang of it mikeologist.

3370Vote UpVote DownSweet, thanks

I'll try to update OPs code and tag you

Floating point numbers will be our downfall; count on it.

Imagine a world without hypothetical situations.

70Vote UpVote DownHi everyone,

firstly, I am thank you for your helps. I solved my problem using uint64_t variable.but I use a lot of mathematical operation on another cogs and ı don't want to slowing my program. Another problem, I use a 2500 pulse incremental rotary encoder. quick start board works good until 120 m/min.but it is can not count the pulses when the speed exceeds 120 m / min. does the quick start board have a high speed counter pin?

3370Vote UpVote DownHere you are reading the pin and using a total of 4 clocks to do so.

Read about the counter in the prop manual. You can find loads of posts here on how to use it. The counter is waaaay faster.

I don't have a C example handy. I use PASM directly.

Floating point numbers will be our downfall; count on it.

Imagine a world without hypothetical situations.