Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix Map function - IntegerDivideByZero #8938#8957

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
TD-er wants to merge3 commits intoesp8266:master
base:master
Choose a base branch
Loading
fromTD-er:bugfix/8938_MapFunction

Conversation

@TD-er
Copy link
Contributor

Fixes:#8938

Also increase accuracy of mapping and fixing map issues with large values. Still only using integer operations.

Test function to see absolute error compared to floating point map function usingdouble precision floating point values.

#include<iostream>#include<string>longtest_map(long x,long in_min,long in_max,long out_min,long out_max) {constdouble out_length = out_max - out_min;constdouble in_length  = in_max - in_min;if (in_length ==0) {return in_min; }if (out_length ==0) {return out_min; }constdouble delta = x - in_min;constdouble value = (delta * out_length + (in_length /2)) / in_length + out_min;//    return std::round(value);return value;}longcheck(long x,long in_min,long in_max,long out_min,long out_max) {constlong floatvalue =test_map(x, in_min, in_max, out_min, out_max);constlong map_value =map(x, in_min, in_max, out_min, out_max);return floatvalue - map_value;}intmain(){long input =0;for (size_t i =0; i <15; ++i) {        input = (i /3) *2500 -1 + i %3;constlong values[] = {check(input,0,1000,255,0),check(input,0,1000,0,255),check(input,10000,0,100,10100),check(input,10000,0,10100,100),check(input,10000,0,0,1024),check(input,10000,0,1024,0),check(input,1000,0,0,10240),check(input,1000,0,10240,0),check(input,0,1000,0,10240),check(input,0,1000,10240,0),check(input,0,10000,10240,0),check(input,10234567, -12345,10234567,100),check(input,10000,0,10234567,0),check(input,50,1,10234567,0)        };        std::cout << input <<":";constexprsize_t nrvalues =sizeof(values) /sizeof(values[0]);for (size_t i =0; i < nrvalues; ++i) {            std::cout <<"\t" << values[i];        }        std::cout <<"\n";    }}

Output:

-1:0-1000-102200-1220:00000000000-1011:-1000-1010011-1002499:1-10000111100002500:110000100100102501:000000200210014999:1-10000111100005000:100000100100115001:000000200210107499:1-10000111100117500:110000100100007501:000000200210109999:1-1000-11111001010000:1000001001000010001:0000-1020022001

Fixes:esp8266#8938Also increase accuracy of mapping and fixing map issues with large values.Still only using integer operations.Test function to see absolute error compared to floating point map function using `double` precision floating point values.```c++# include <iostream># include <string>long test_map(long x, long in_min, long in_max, long out_min, long out_max) {    const double out_length = out_max - out_min;    const double in_length  = in_max - in_min;    if (in_length == 0) { return in_min; }    if (out_length == 0) { return out_min; }    const double delta = x - in_min;    const double value = (delta * out_length + (in_length / 2)) / in_length + out_min;//    return std::round(value);    return value;}long check(long x, long in_min, long in_max, long out_min, long out_max) {    const long floatvalue = test_map(x, in_min, in_max, out_min, out_max);    const long map_value = map(x, in_min, in_max, out_min, out_max);    return floatvalue - map_value;}int main(){    long input = 0;    for (size_t i = 0; i < 15; ++i) {        input = (i / 3) * 2500 - 1 + i % 3;        const long values[] = {            check(input, 0,        1000,   255,      0),            check(input, 0,        1000,   0,        255),            check(input, 10000,    0,      100,      10100),            check(input, 10000,    0,      10100,    100),            check(input, 10000,    0,      0,        1024),            check(input, 10000,    0,      1024,     0),            check(input, 1000,     0,      0,        10240),            check(input, 1000,     0,      10240,    0),            check(input, 0,        1000,   0,        10240),            check(input, 0,        1000,   10240,    0),            check(input, 0,        10000,  10240,    0),            check(input, 10234567, -12345, 10234567, 100),            check(input, 10000,    0,      10234567, 0),            check(input, 50,       1,      10234567, 0)        };        std::cout << input << ":";        constexpr size_t nrvalues = sizeof(values) / sizeof(values[0]);        for (size_t i = 0; i < nrvalues; ++i) {            std::cout << "\t" << values[i];        }        std::cout << "\n";    }}```Output:```-1:0-1000-102200-1220:00000000000-1011:-1000-1010011-1002499:1-10000111100002500:110000100100102501:000000200210014999:1-10000111100005000:100000100100115001:000000200210107499:1-10000111100117500:110000100100007501:000000200210109999:1-1000-11111001010000:1000001001000010001:0000-1020022001```
Not really a need to make a recursive call for simply swapping values.
@d-a-v
Copy link
Collaborator

Why isin_min returned when input range is 0? Why notout_min or(out_min + out_max)/2 ?
User always expects to get a value of the same order asout_min..out_max.

Thearduino reference is

longmap(longx,longin_min,longin_max,longout_min,longout_max) {return (x-in_min)* (out_max-out_min) / (in_max-in_min)+out_min;}

The issue is the division by 0, why notjust handling this case ?
How would this compare with yourtest_map() (with fixed return when input range is 0)

@TD-er
Copy link
ContributorAuthor

TD-er commentedJul 18, 2023
edited
Loading

In the latest commit this was alread addressed, as I also noticed this odd choice of mine :)

if (in_length ==0 || out_length ==0) {return out_min;     }

I guess returing the average of the output range also makes sense, but might be harder to detect?

The issue is the division by 0, why notjust handling this case ?

Because there were more issues with map, as it was experiencing integer overflow issues quite easily.
You don't need to get really high values to experience those overflow issues.
Only withdelta anddividend (renamed toout_range in my code as I constantly got confused) approaching 31 bits in size would already result in overflow issues.

How would this compare with your test_map() (with fixed return when input range is 0)

Just tested it and it will just return what has been given as out_min value.
Thus before the 'swap' of values.
map(X, N, N, out_min, out_max) will returnout_min.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Map function - IntegerDivideByZero

2 participants

@TD-er@d-a-v

[8]ページ先頭

©2009-2025 Movatter.jp