Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

How to proportionally convert a number in the range of -1 and 1 to a number in the range of 0 and 319

+3
−2

I have float noise values, between -1 and 1, for every x,y coordinate in a 2D area and I am trying to convert that to a whole number between 0 and 319 which represents a vertical z coordinate to render.

For example,

-1 = 0 and   
1 = 319 but    
0.12345 = ???

How would I go about implementing this efficiently?

History
Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

2 comment threads

How many such conversions are required (3 comments)
Not sure if I understood entirely your question, but it seems to boil down to a simple set of equatio... (1 comment)

3 answers

+10
−0

There is one thing to clarify when mapping a float interval to an integer interval, namely how the boundaries of the float interval shall be mapped to the boundaries of the integer interval.

Taking the example of the float interval [-1.0, +1.0], assuming here, that the endpoints of the interval can actually occur. If the target integer interval is 0..319: Which floating point interval shall be mapped to 0?

If we linearly map [-1.0, +1.0] to [0.0, 319.0] then this gives (as others have explained) the following formula: y = 159.5x + 159.5.

When rounding is done to the nearest integer this will have the following effect:

  • float numbers [-1.0, −0,996865204] will be mapped to 0. This interval has a width of 0,003134796.
  • float numbers [−0,996865205, −0,990595611] will be mapped to 1. This interval has a width of 0,006269593.
  • float numbers [0,996865204, +1,0] will be mapped to 319. This interval has a width of 0,003134796.

You see that the ranges of float values that map to 0 and 319 are only half as wide as the ranges of float values that map to numbers from 1..318. This may be exactly what you want, or it may be acceptable, in which case the formula y = 159.5x + 159.5 is perfectly fine.

For other rounding strategies (round towards minus infinity, round towards plus infinity) the results will be different, but there will still be an asymmetry with respect to the width of the intervals for some the numbers.

If instead you want to achieve that for each target integer number the source intervals shall be equally wide, then you would have to calculate the mapping from [-1.0, +1.0] to [-0.5, 319.5). This would result in the formula y = 160.0*x + 159.5 with rounding, giving the desired numbers from 0..319, plus a special case handling of +1.0 which would have to be mapped to 319 rather than 320.

History
Why does this post require moderator attention?
You might want to add some details to your flag.

0 comment threads

+8
−0

You want to scale from one linear range to another. That can always be done with

    y = mx + b

where X is the input value and Y the output value. M is the scale factor, and B the offset.

You want to map (-1 .. 1) to (0 .. 319). The scale factor therefore has to be 319/2 = 159.5 = m.

Now that you know M, pick any known X and Y pair and solve for B:

    b = y - mx

You know that -1 maps to 0, so

    y - mx = 0 - (159.5)(-1) = 159.5 = b

The final result is therefore

    y = 159.5x + 159.5

Note that this method works for mapping any linear range to any other linear range.

History
Why does this post require moderator attention?
You might want to add some details to your flag.

0 comment threads

+5
−0

My initial approach would be to increase n by 1 (thus shifting the original range from -1..+1 to 0..+2), turn that range into 0..+1, and then simply map from that to your 0..+319 output range.

float result = (n+1)/2 * 319;

This will map -1 to 0; 0 to 159.5; +1 to 319; and your example +0.12345 to 179.190275. (All potentially subject to float precision issues, of course.)

As for efficiency, this is a few simple math operations; I'm not sure you can get much more efficient than that. That problem is complicated by the fact that you are dealing with a floating-point value as the input.

Once you have the corresponding floating-point value, just use whatever rounding function you prefer. java.lang.Math offers e.g. floor() and rint(), or if you think you can do better then you can roll your own rounding function.

Had the input value n been an integer, you could probably just have precomputed a fairly small (320 entries in this case) table and benchmarked on-need calculation and table lookup respectively on application startup and used the faster approach, paying attention to things like cache locality, but this feels as though if that's the level of optimization you are looking for, then Java is the wrong language to use to begin with.

History
Why does this post require moderator attention?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »