Comments (6)
Unfortunately this is a limitation that I currently don't have a work around for.
Fixed point multiplication results in a type twice as large as the source type, which is then scaled back down to the appropriate type.
For example, in the case of UQ8x8
it results in a UQ16x16
, which is then scaled back down to a UQ8x8
to give the final result.
(There's also a multiply
function that doesn't scale back down, in case the larger precision is wanted for some reason.)
In the case of UQ32x32
, which is backed by a uint64_t
and similarly SQ31x32
, which is backed by an int64_t
, i.e. both require 64 bits to be stored.
When multiplying either of these, the resulting type would require 128 bits to be stored.
But there is no 128 bit type by default (i.e. no uint128_t
or int128_t
), so to fix the issue I'd have to either introduce one or introduce a workaround that can reliably achieve 128 bit multiplication.
That would mean implementing a multiplication algorithm instead of being able to rely on the compiler to generate the appropriate multiplication code, which would take a fair bit of research beforehand.
Truth be told, when I originally wrote this I wasn't anticipating people wanting to use the 64 bit-backed types because I wasn't aware of the ARM-based Arduino MCUs, I was only aware of the AVR-based ones which can only realistically achieve 32-bit backed, 16-bit backed ant 8-bit backed variations.
from fixedpointsarduino.
Hi,
Thanks for your reply!
That was what I was expecting about the multiplication issue!!!
However, I'd like to ask you about another issue!
If I do the multiplication:
SQ15x16 x = 320.153;
SQ15x16 y = 0.000200;
SQ15x16 z = 0.0;
z = x*y;
The result is z = 0.06349182 however the real value is 0.06403060, that means the error is 0.008. If you are using 16 bits for the decimal part, the resolution should be 2^-16 = 0.00001525878. Thus, why the error started in the thousandth part?
Best regards.
Nuno Vilhena
from fixedpointsarduino.
The error happens when the floats are first converted as well, not just during the multiplication.
320.153 gets stored as 320.1530151367187500 (320 + 10028/65536)
0.0002 gets stored as 0.0001983642578125 (0 + 13/65536)
320.1530151367187500 * 0.0001983642578125 = 0.063506915234029293060302734375
((320 + 10028/65536) * (0 + 13/65536) = (0 + 4161/65536))
So actually 0.0634918212890625 isn't too far off.
Unfortunately you'll always have some amount of error because of the difficulty of expressing decimal fractions in binary.
For example, you can't exactly store 0.153.
Using SQ15x16 the closest you can get is either:
10028 / 65536 = 0.15301513671875
10027 / 65536 = 0.1529998779296875
If you know that the integer part will have a limited range then you can improve the precision of the fractional part.
For example, if you know the integer part isn't going to exceed 2000 then you could make your own type alias using SQ11x20 = SFixed<11, 20>;
, which would give you greater precision.
Using SFixed<11, 20>
gets a final result of 0.0638113021850585.
Using SFixed<10, 21>
gets a final result of 0.0639648437500000.
Using SFixed<9, 22>
gets a final result of 0.0639648437500000.
(And so on.)
Even a full 32 bits of fraction would only be able to represent 0.153 as 0.1529999971389770.
In fact I'm not sure how many bits you'd need to actually manage to represent it properly using a fraction-over-power-of-two approach, it might not be possible.
Ultimately depending on what you're calculating, fixed points might not actually be the best solution.
Fixed points are better for dealing with smaller ranges of values.
If you need to cover a large range of values that have both a large integer part and a large fractional part then floating points probably are more suitable.
from fixedpointsarduino.
As it has been 5 days since the last post,
I'm considering closing this issue.
@nunovilhena,
Have I successfully answered your questions?
Is there something you think I should do to make this problem more obvious in the library documentation or the library source (e.g. give a clearer error message)?
from fixedpointsarduino.
Hello Pharap,
Sorry my late reply but this week is being very stressful for me!
About my question, yes, you have.
If you could include something to advise about those limitations, should be better yes. About the multiplication/ division limitations and how the conversions between float to fixed_point is done (to show why there are a error in the calculations with your library!
So, you can close this issue, many thanks!
Nuno Vilhena
from fixedpointsarduino.
It's ok, I wasn't trying to rush you.
I just thought you might have intended to reply and then forgotten because you had other things to do.
(I have sometimes forgotten to press 'send'/'comment' on messages before and only realised the next day.)
I have opened a second issue (#23) to remind myself to add a proper explanation.
As I have answered all your questions, I will close this issue.
from fixedpointsarduino.
Related Issues (20)
- Support the use of volatile HOT 2
- Add more integer cast operators HOT 2
- Add bitshift operators HOT 6
- Replace use of void in zero-parameter functions
- Use of 'inline' in 'RawType' is redundant
- Add support for postincrement and postdecrement HOT 3
- Provide trigonometry functions HOT 1
- Disable random number functionality for non-AVR boards
- Add random number support for other board targets
- Update the dates on all licence headers
- Replace use of LargerType in constructors with ShiftType HOT 1
- Fix shift overflow bug in preincrement and predecrement operators
- Consider replacing some member functions and operators with free functions
- Consider providing constants in a separate namespace
- Provide formatting and printing functions
- Consider providing templates implementing other ways of expressing fixed points
- Add template aliases SQ and UQ in FixedPointsCommon
- Investigate the potential of adding specalisations for fixed points with zero-width fractions
- Make casting negative numbers more predictable. HOT 2
- Converting to float provides an incorrect result for certain types.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fixedpointsarduino.