Map range: Difference between revisions

From Rosetta Code
Content added Content deleted
mNo edit summary
m (→‎{{header|Wren}}: Changed to Wren S/H)
(38 intermediate revisions by 19 users not shown)
Line 25: Line 25:
{{trans|Python}}
{{trans|Python}}


<lang 11l>F maprange(a, b, s)
<syntaxhighlight lang="11l">F maprange(a, b, s)
R b[0] + (Float(s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]))
R b[0] + (Float(s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]))


L(s) 0..10
L(s) 0..10
print(‘#2 maps to #.’.format(s, maprange((0, 10), (-1, 0), s)))</lang>
print(‘#2 maps to #.’.format(s, maprange((0, 10), (-1, 0), s)))</syntaxhighlight>


{{out}}
{{out}}
Line 45: Line 45:
10 maps to 0
10 maps to 0
</pre>
</pre>

=={{header|6502 Assembly}}==
A range like [0, n] for some natural number <code>n < 255</code> can be easily mapped with a lookup table. The second range can be anything, as long as each entry is the same length and are stored consecutively in the desired order. This method requires a bit of compile-time knowledge, but is very efficient in terms of speed. Each element <code>Bn</code> is stored at relative offset <code>An</code> .

<syntaxhighlight lang="6502asm">mapping:
byte $00,$00,$80,$BF ;-1.0f (stored little-endian so the bytes are backwards)
byte $66,$66,$66,$BF ;-0.9f
byte $CD,$CC,$4C,$BF ;-0.8f
byte $33,$33,$33,$BF ;-0.7f
etc.</syntaxhighlight>

If the range isn't [0, n], but begins at some other natural number [k, n] where <tt>k,n < 255 </tt>, we can express it as [0, n-k] instead and simply subtract the "key" at runtime to get the offset.

This method is very convenient for implementing ASCII into hardware that lacks a built-in system font (like the NES). You can save graphics memory by mapping tile number 0 to ASCII 32, tile number 01 to 33, and so on. Had you mapped them "correctly," (i.e. tile number 32 to ASCII 32) you would still need a "blank tile" as tile number zero. So the easier solution is to subtract 32 from the character code before printing.

<syntaxhighlight lang="6502asm">;runs during non-maskable interrupt.
PrintChar:
;a = char to print
SEC
SBC #$32 ;subtract ascii offset to map the index to the correct tile graphics data.

;everything below this comment is hardware-specific mumbo-jumbo, feel free to ignore it if you don't care.
;ideally you'd want to do this before getting here so that the only thing that happens during NMI is the write to vram.
pha
LDA Cursor_Y
ASL
ASL
ASL
ASL
ASL
STA tempY ;row * 32
LDA #$20
ADC Cursor_X
STA tempX
LDA $2002 ;reset picture processor high-low latch
LDA tempX
STA $2006 ;this register is big-endian for some reason. Which is why I had to store Cursor_Y << 5 into tempY rather than here directly.
LDA tempY
STA $2006
PLA
STA $2007</syntaxhighlight>


=={{header|ACL2}}==
=={{header|ACL2}}==


<lang Lisp>(defun mapping (a1 a2 b1 b2 s)
<syntaxhighlight lang="lisp">(defun mapping (a1 a2 b1 b2 s)
(+ b1 (/ (* (- s a1)
(+ b1 (/ (* (- s a1)
(- b2 b1))
(- b2 b1))
Line 63: Line 104:
;; (-1 -9/10 -4/5 -7/10 -3/5 -1/2 -2/5 -3/10 -1/5 -1/10 0)
;; (-1 -9/10 -4/5 -7/10 -3/5 -1/2 -2/5 -3/10 -1/5 -1/10 0)


</syntaxhighlight>
</lang>

=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
<syntaxhighlight lang="action!">INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit

PROC Map(REAL POINTER a1,a2,b1,b2,s,res)
REAL tmp1,tmp2,tmp3

RealSub(s,a1,tmp1) ;tmp1=s-a1
RealSub(b2,b1,tmp2) ;tmp2=b2-b1
RealMult(tmp1,tmp2,tmp3) ;tmp3=(s-a1)*(b2-b1)
RealSub(a2,a1,tmp1) ;tmp1=a2-a1
RealDiv(tmp3,tmp1,tmp2) ;tmp2=(s-a1)*(b2-b1)/(a2-a1)
RealAdd(b1,tmp2,res) ;res=b1+(s-a1)*(b2-b1)/(a2-a1)
RETURN

PROC Main()
BYTE i
REAL a1,a2,b1,b2,s,res

Put(125) PutE() ;clear screen

ValR("0",a1) ValR("10",a2)
ValR("-1",b1) ValR("0",b2)

FOR i=0 TO 10
DO
IntToReal(i,s)
Map(a1,a2,b1,b2,s,res)
PrintR(s) Print(" maps to ")
PrintRE(res)
OD
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Map_range.png Screenshot from Atari 8-bit computer]
<pre>
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0
</pre>


=={{header|Ada}}==
=={{header|Ada}}==


<lang Ada>with Ada.Text_IO;
<syntaxhighlight lang="ada">with Ada.Text_IO;
procedure Map is
procedure Map is
type First_Range is new Float range 0.0 .. 10.0;
type First_Range is new Float range 0.0 .. 10.0;
Line 99: Line 188:
Test_Value := Test_Value + 1.0;
Test_Value := Test_Value + 1.0;
end loop;
end loop;
end Map;</lang>
end Map;</syntaxhighlight>


{{out}}
{{out}}
Line 115: Line 204:


=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
<lang algol68># maps a real s in the range [ a1, a2 ] to the range [ b1, b2 ] #
<syntaxhighlight lang="algol68"># maps a real s in the range [ a1, a2 ] to the range [ b1, b2 ] #
# there are no checks that s is in the range or that the ranges are valid #
# there are no checks that s is in the range or that the ranges are valid #
PROC map range = ( REAL s, a1, a2, b1, b2 )REAL:
PROC map range = ( REAL s, a1, a2, b1, b2 )REAL:
Line 123: Line 212:
FOR i FROM 0 TO 10 DO
FOR i FROM 0 TO 10 DO
print( ( whole( i, -2 ), " maps to ", fixed( map range( i, 0, 10, -1, 0 ), -8, 2 ), newline ) )
print( ( whole( i, -2 ), " maps to ", fixed( map range( i, 0, 10, -1, 0 ), -8, 2 ), newline ) )
OD</lang>
OD</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 137: Line 226:
9 maps to -0.10
9 maps to -0.10
10 maps to 0.00
10 maps to 0.00
</pre>
=={{header|Amazing Hopper}}==
La función "Seqspaced" es una macro-sustitución de "seqsp", y está construida, internamente, como una rutina en C que realiza el siguiente cálculo (en pseudocódigo):
<syntaxhighlight lang="c">
double inc = (nHasta - nDesde) / ( nTotal - 1);
lista[0] = nDesde;
lista[nTotal] = nHasta;
for( n=1; n<nTotal; n++){
lista[n] = lista[n-1] + inc;
}
</syntaxhighlight>
Macro-sustitución de "Seqspaced":
<syntaxhighlight lang="amazing hopper">
#defn Seqspaced(__X__,__Y__,__Z__,_V_) #ATOM#CMPLX;#ATOM#CMPLX;#ATOM#CMPLX;keep;lthan(1);\
do{{"Seqspaced: num elements < 1"}throw(2301)},seqsp(_V_)
</syntaxhighlight>
Otras macrosustituciones:
<syntaxhighlight lang="amazing hopper">
#defn Toksep(__X__) #ATOM#CMPLX;toksep;
#defn Cat(_X_,*) #ATOM#CMPLX;#GENCODE $$$*$$$ #ATCMLIST;cat; #ENDGEN
#defn Justleft(_X_,_V_) {" "};#ATOM#CMPLX;#ATOM#CMPLX;padright;
</syntaxhighlight>
Código que resuelve la tarea:
<syntaxhighlight lang="amazing hopper">
#include <jambo.h>
Main
v=0,w=0
Seqspaced(-1,0,11,w) // [-1,0}->[0-10]=11 números
Seqspaced(0,10,11,v)
Toksep( "\n" )
Cat( Justright(5,Str(v))," => ",Justright(5,Str(w))), Prnl
End
</syntaxhighlight>
{{out}}
<pre>
$ hopper maprange.jambo
0 => -1
1 => -0.9
2 => -0.8
3 => -0.7
4 => -0.6
5 => -0.5
6 => -0.4
7 => -0.3
8 => -0.2
9 => -0.1
10 => 0
$
</pre>
</pre>


=={{header|AppleScript}}==
=={{header|AppleScript}}==
<lang applescript>------------------------ MAP RANGE -----------------------
<syntaxhighlight lang="applescript">------------------------ MAP RANGE -----------------------


-- rangeMap :: (Num, Num) -> (Num, Num) -> Num -> Num
-- rangeMap :: (Num, Num) -> (Num, Num) -> Num -> Num
Line 443: Line 580:
return lst
return lst
end tell
end tell
end zipWith3</lang>
end zipWith3</syntaxhighlight>
{{Out}}
{{Out}}
<pre> 0 -> -1.0 = -1/1
<pre> 0 -> -1.0 = -1/1
Line 459: Line 596:
=={{header|Arturo}}==
=={{header|Arturo}}==


<lang rebol>getMapped: function [a,b,i][
<syntaxhighlight lang="rebol">getMapped: function [a,b,i][
round .to:1 b\0 + ((i - a\0) * (b\1 - b\0))/(a\1 - a\0)
round .to:1 b\0 + ((i - a\0) * (b\1 - b\0))/(a\1 - a\0)
]
]
Line 469: Line 606:
mapped: getMapped rangeA rangeB to :floating x
mapped: getMapped rangeA rangeB to :floating x
print [x "maps to" mapped]
print [x "maps to" mapped]
]</lang>
]</syntaxhighlight>


{{out}}
{{out}}
Line 487: Line 624:
=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
{{trans|C}}
{{trans|C}}
<syntaxhighlight lang="autohotkey">
<lang AutoHotkey>
mapRange(a1, a2, b1, b2, s)
mapRange(a1, a2, b1, b2, s)
{
{
Line 498: Line 635:
out .= "f(" A_Index-1 ") = " mapRange(0,10,-1,0,A_Index-1) "`n"
out .= "f(" A_Index-1 ") = " mapRange(0,10,-1,0,A_Index-1) "`n"
MsgBox % out
MsgBox % out
</syntaxhighlight>
</lang>


=={{header|AWK}}==
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f MAP_RANGE.AWK
# syntax: GAWK -f MAP_RANGE.AWK
BEGIN {
BEGIN {
Line 516: Line 653:
return b1 + ((num-a1) * (b2-b1) / (a2-a1))
return b1 + ((num-a1) * (b2-b1) / (a2-a1))
}
}
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 534: Line 671:
=={{header|Axiom}}==
=={{header|Axiom}}==
Axiom provides a Segment domain for intervals. The following uses a closure for a mapRange function over fields, which provides for some generality.
Axiom provides a Segment domain for intervals. The following uses a closure for a mapRange function over fields, which provides for some generality.
<lang Axiom>)abbrev package TESTP TestPackage
<syntaxhighlight lang="axiom">)abbrev package TESTP TestPackage
TestPackage(R:Field) : with
TestPackage(R:Field) : with
mapRange: (Segment(R), Segment(R)) -> (R->R)
mapRange: (Segment(R), Segment(R)) -> (R->R)
Line 540: Line 677:
mapRange(fromRange, toRange) ==
mapRange(fromRange, toRange) ==
(a1,a2,b1,b2) := (lo fromRange,hi fromRange,lo toRange,hi toRange)
(a1,a2,b1,b2) := (lo fromRange,hi fromRange,lo toRange,hi toRange)
(x:R):R +-> b1+(x-a1)*(b2-b1)/(a2-a1)</lang>
(x:R):R +-> b1+(x-a1)*(b2-b1)/(a2-a1)</syntaxhighlight>
Use:<lang Axiom>f := mapRange(1..10,a..b)
Use:<syntaxhighlight lang="axiom">f := mapRange(1..10,a..b)
[(xi,f xi) for xi in 1..10]</lang>
[(xi,f xi) for xi in 1..10]</syntaxhighlight>
{{out}}
{{out}}
<pre> b + 8a 2b + 7a b + 2a 4b + 5a 5b + 4a
<pre> b + 8a 2b + 7a b + 2a 4b + 5a 5b + 4a
Line 555: Line 692:
==={{header|BASIC256}}===
==={{header|BASIC256}}===
{{trans|FreeBASIC}}
{{trans|FreeBASIC}}
<lang BASIC256>function MapRange(s, a1, a2, b1, b2)
<syntaxhighlight lang="basic256">function MapRange(s, a1, a2, b1, b2)
return b1+(s-a1)*(b2-b1)/(a2-a1)
return b1+(s-a1)*(b2-b1)/(a2-a1)
end function
end function
Line 562: Line 699:
print i; " maps to "; MapRange(i,0,10,-1,0)
print i; " maps to "; MapRange(i,0,10,-1,0)
next i
next i
end</lang>
end</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 570: Line 707:
==={{header|BBC BASIC}}===
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
{{works with|BBC BASIC for Windows}}
<lang bbcbasic> @% = 5 : REM Column width
<syntaxhighlight lang="bbcbasic"> @% = 5 : REM Column width
DIM range{l, h}
DIM range{l, h}
DIM A{} = range{}, B{} = range{}
DIM A{} = range{}, B{} = range{}
Line 581: Line 718:
DEF FNmaprange(a{}, b{}, s)
DEF FNmaprange(a{}, b{}, s)
= b.l + (s - a.l) * (b.h - b.l) / (a.h - a.l)</lang>
= b.l + (s - a.l) * (b.h - b.l) / (a.h - a.l)</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 598: Line 735:


==={{header|Commodore BASIC}}===
==={{header|Commodore BASIC}}===
<lang commodorebasic>10 REM MAP RANGE
<syntaxhighlight lang="commodorebasic">10 REM MAP RANGE
20 REM COMMODORE BASIC 2.0
20 REM COMMODORE BASIC 2.0
30 REM ================================
30 REM ================================
Line 606: Line 743:
70 FOR S=0 TO 10
70 FOR S=0 TO 10
80 PRINT S;"MAPS TO ";FN MR(S)
80 PRINT S;"MAPS TO ";FN MR(S)
90 NEXT</lang>
90 NEXT</syntaxhighlight>


{{out}}
{{out}}
Line 624: Line 761:


==={{header|IS-BASIC}}===
==={{header|IS-BASIC}}===
<lang IS-BASIC>100 PROGRAM "MapRange.bas"
<syntaxhighlight lang="is-basic">100 PROGRAM "MapRange.bas"
110 LET A1=0:LET A2=10
110 LET A1=0:LET A2=10
120 LET B1=-1:LET B2=0
120 LET B1=-1:LET B2=0
Line 630: Line 767:
140 FOR I=0 TO 10
140 FOR I=0 TO 10
150 PRINT I;"maps to ";MR(I)
150 PRINT I;"maps to ";MR(I)
160 NEXT</lang>
160 NEXT</syntaxhighlight>


=={{header|bc}}==
=={{header|bc}}==
<lang bc>/* map s from [a, b] to [c, d] */
<syntaxhighlight lang="bc">/* map s from [a, b] to [c, d] */
define m(a, b, c, d, s) {
define m(a, b, c, d, s) {
return (c + (s - a) * (d - c) / (b - a))
return (c + (s - a) * (d - c) / (b - a))
Line 648: Line 785:
i; " => "; m(0, 10, -1, 0, i)
i; " => "; m(0, 10, -1, 0, i)
}
}
quit</lang>
quit</syntaxhighlight>


{{out}}
{{out}}
Line 670: Line 807:
<code>_map_</code> is a 2-modifier which returns a mapping function given two ranges.
<code>_map_</code> is a 2-modifier which returns a mapping function given two ranges.


<lang bqn>_map_ ← {
<syntaxhighlight lang="bqn">_map_ ← {
a1‿a2 _𝕣_ b1‿b2 s:
a1‿a2 _𝕣_ b1‿b2 s:
b1 + ((s - a1) × b2 - b1) ÷ a2 - a1
b1 + ((s - a1) × b2 - b1) ÷ a2 - a1
Line 678: Line 815:


•Show ZeroTen 0.1
•Show ZeroTen 0.1
•Show ZeroTen 8</lang>
•Show ZeroTen 8</syntaxhighlight>
<lang bqn>¯0.99
<syntaxhighlight lang="bqn">¯0.99
¯0.19999999999999996</lang>
¯0.19999999999999996</syntaxhighlight>
[https://mlochbaum.github.io/BQN/try.html#code=X21hcF8g4oaQIHsKIGEx4oC/YTIgX/CdlaNfIGIx4oC/YjIgczoKIGIxICsgKChzIC0gYTEpIMOXIGIyIC0gYjEpIMO3IGEyIC0gYTEKfQoKWmVyb1RlbiDihpAgMOKAvzEwIF9tYXBfIMKvMeKAvzAKCuKAolNob3cgWmVyb1RlbiAwLjEK4oCiU2hvdyBaZXJvVGVuIDEw Try It!]
[https://mlochbaum.github.io/BQN/try.html#code=X21hcF8g4oaQIHsKIGEx4oC/YTIgX/CdlaNfIGIx4oC/YjIgczoKIGIxICsgKChzIC0gYTEpIMOXIGIyIC0gYjEpIMO3IGEyIC0gYTEKfQoKWmVyb1RlbiDihpAgMOKAvzEwIF9tYXBfIMKvMeKAvzAKCuKAolNob3cgWmVyb1RlbiAwLjEK4oCiU2hvdyBaZXJvVGVuIDEw Try It!]
=={{header|Bracmat}}==
=={{header|Bracmat}}==
{{trans|C}}
{{trans|C}}
<lang bracmat>( ( mapRange
<syntaxhighlight lang="bracmat">( ( mapRange
= a1,a2,b1,b2,s
= a1,a2,b1,b2,s
. !arg:(?a1,?a2.?b1,?b2.?s)
. !arg:(?a1,?a2.?b1,?b2.?s)
Line 696: Line 833:
& 1+!n:?n
& 1+!n:?n
)
)
);</lang>
);</syntaxhighlight>
{{out}}
{{out}}
<pre>Mapping [0,10] to [-1,0] at intervals of 1:
<pre>Mapping [0,10] to [-1,0] at intervals of 1:
Line 712: Line 849:


=={{header|C}}==
=={{header|C}}==
<lang C>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>


double mapRange(double a1,double a2,double b1,double b2,double s)
#define mapRange(a1,a2,b1,b2,s) (b1 + (s-a1)*(b2-b1)/(a2-a1))
{
return b1 + (s-a1)*(b2-b1)/(a2-a1);
}


int main()
int main()
Line 731: Line 865:
return 0;
return 0;
}
}
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 748: Line 882:


=={{header|C sharp}}==
=={{header|C sharp}}==
<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;
using System.Linq;
using System.Linq;


Line 759: Line 893:
static double Map(double a1, double a2, double b1, double b2, double s) => b1 + (s - a1) * (b2 - b1) / (a2 - a1);
static double Map(double a1, double a2, double b1, double b2, double s) => b1 + (s - a1) * (b2 - b1) / (a2 - a1);
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 779: Line 913:
It's not written efficiently; certainly, there can be fewer explicit temporary variables. The use of the template offers a choice in types for precision and accuracy considerations, though one area for improvement might be to allow a different type for intermediate calculations.
It's not written efficiently; certainly, there can be fewer explicit temporary variables. The use of the template offers a choice in types for precision and accuracy considerations, though one area for improvement might be to allow a different type for intermediate calculations.


<lang cpp>#include <iostream>
<syntaxhighlight lang="cpp">#include <iostream>
#include <utility>
#include <utility>


Line 804: Line 938:


return 0;
return 0;
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 824: Line 958:
{{trans|Python}}
{{trans|Python}}


<lang clojure>
<syntaxhighlight lang="clojure">
(defn maprange [[a1 a2] [b1 b2] s]
(defn maprange [[a1 a2] [b1 b2] s]
(+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))
(+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))
Line 842: Line 976:
9 maps to -1/10
9 maps to -1/10
10 maps to 0
10 maps to 0
</syntaxhighlight>
</lang>


=={{header|COBOL}}==
=={{header|COBOL}}==
{{works with|OpenCOBOL}}
{{works with|OpenCOBOL}}
<lang cobol> IDENTIFICATION DIVISION.
<syntaxhighlight lang="cobol"> IDENTIFICATION DIVISION.
PROGRAM-ID. demo-map-range.
PROGRAM-ID. demo-map-range.


Line 898: Line 1,032:
/ (a-end - a-begin))
/ (a-end - a-begin))
.
.
END PROGRAM map-range.</lang>
END PROGRAM map-range.</syntaxhighlight>


The output is identical to the output of the Common Lisp example.
The output is identical to the output of the Common Lisp example.
Line 904: Line 1,038:
=={{header|CoffeeScript}}==
=={{header|CoffeeScript}}==


<syntaxhighlight lang="coffeescript ">
<lang CoffeeScript >
mapRange = (a1,a2,b1,b2,s) ->
mapRange = (a1,a2,b1,b2,s) ->
t = b1 + ((s-a1)*(b2 - b1)/(a2-a1))
t = b1 + ((s-a1)*(b2 - b1)/(a2-a1))
Line 910: Line 1,044:
for s in [0..10]
for s in [0..10]
console.log("#{s} maps to #{mapRange(0,10,-1,0,s)}")
console.log("#{s} maps to #{mapRange(0,10,-1,0,s)}")
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 927: Line 1,061:


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
<lang lisp>(defun map-range (a1 a2 b1 b2 s)
<syntaxhighlight lang="lisp">(defun map-range (a1 a2 b1 b2 s)
(+ b1
(+ b1
(/ (* (- s a1)
(/ (* (- s a1)
Line 937: Line 1,071:
do (format t "~F maps to ~F~C" i
do (format t "~F maps to ~F~C" i
(map-range 0 10 -1 0 i)
(map-range 0 10 -1 0 i)
#\Newline))</lang>
#\Newline))</syntaxhighlight>


{{out}}
{{out}}
Line 951: Line 1,085:
9.0 maps to -0.1
9.0 maps to -0.1
10.0 maps to 0.0</pre>
10.0 maps to 0.0</pre>

=={{header|Craft Basic}}==
<syntaxhighlight lang="basic">define a1 = 0, b1 = 0, a2 = 0, b2 = 0

for i = 0 to 10

let s = i
let a1 = 0
let a2 = 10
let b1 = -1
let b2 = 0

print i, " : ", b1 + ( s - a1 ) * ( b2 - b1 ) / ( a2 - a1 )

next i</syntaxhighlight>
{{out| Output}}<pre>0 : -1
1 : -0.9000
2 : -0.8000
3 : -0.7000
4 : -0.6000
5 : -0.5000
6 : -0.4000
7 : -0.3000
8 : -0.2000
9 : -0.1000
10 : 0</pre>


=={{header|D}}==
=={{header|D}}==
<lang d>double mapRange(in double[] a, in double[] b, in double s)
<syntaxhighlight lang="d">double mapRange(in double[] a, in double[] b, in double s)
pure nothrow @nogc {
pure nothrow @nogc {
return b[0] + ((s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]));
return b[0] + ((s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]));
Line 965: Line 1,125:
foreach (immutable s; 0 .. 11)
foreach (immutable s; 0 .. 11)
writefln("%2d maps to %5.2f", s, mapRange(r1, r2, s));
writefln("%2d maps to %5.2f", s, mapRange(r1, r2, s));
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre> 0 maps to -1.00
<pre> 0 maps to -1.00
Line 982: Line 1,142:
=={{header|EchoLisp}}==
=={{header|EchoLisp}}==
EchoLisp provides several native interpolation functions: smoothstep, s-curve, .. and '''linear''' which performs linear interpolation.
EchoLisp provides several native interpolation functions: smoothstep, s-curve, .. and '''linear''' which performs linear interpolation.
<lang scheme>
<syntaxhighlight lang="scheme">
(lib 'plot) ;; interpolation functions
(lib 'plot) ;; interpolation functions
(lib 'compile)
(lib 'compile)
Line 1,013: Line 1,173:
8 -1/5 -0.2
8 -1/5 -0.2
9 -1/10 -0.1
9 -1/10 -0.1
</syntaxhighlight>
</lang>


=={{header|Elixir}}==
=={{header|Elixir}}==
<lang elixir>defmodule RC do
<syntaxhighlight lang="elixir">defmodule RC do
def map_range(a1 .. a2, b1 .. b2, s) do
def map_range(a1 .. a2, b1 .. b2, s) do
b1 + (s - a1) * (b2 - b1) / (a2 - a1)
b1 + (s - a1) * (b2 - b1) / (a2 - a1)
Line 1,024: Line 1,184:
Enum.each(0..10, fn s ->
Enum.each(0..10, fn s ->
:io.format "~2w map to ~7.3f~n", [s, RC.map_range(0..10, -1..0, s)]
:io.format "~2w map to ~7.3f~n", [s, RC.map_range(0..10, -1..0, s)]
end)</lang>
end)</syntaxhighlight>


{{out}}
{{out}}
Line 1,042: Line 1,202:


=={{header|Emacs Lisp}}==
=={{header|Emacs Lisp}}==
<lang lisp>(defun maprange (a1 a2 b1 b2 s)
<syntaxhighlight lang="lisp">(defun maprange (a1 a2 b1 b2 s)
(+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))
(+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))
(dotimes (i 10)
(dotimes (i 10)
(princ (maprange 0.0 10.0 -1.0 0.0 i))
(message "%s" (maprange 0.0 10.0 -1.0 0.0 i)))</syntaxhighlight>
(terpri))</lang>


=={{header|Erlang}}==
=={{header|Erlang}}==
<lang erlang>-module(map_range).
<syntaxhighlight lang="erlang">-module(map_range).
-export([map_value/3]).
-export([map_value/3]).


map_value({A1,A2},{B1,B2},S) ->
map_value({A1,A2},{B1,B2},S) ->
B1 + (S - A1) * (B2 - B1) / (A2 - A1).
B1 + (S - A1) * (B2 - B1) / (A2 - A1).
</syntaxhighlight>
</lang>


=={{header|ERRE}}==
=={{header|ERRE}}==
<lang ERRE>PROGRAM RANGE
<syntaxhighlight lang="erre">PROGRAM RANGE


BEGIN
BEGIN
Line 1,069: Line 1,228:
END FOR
END FOR
END PROGRAM
END PROGRAM
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre> 0 maps to -1.00
<pre> 0 maps to -1.00
Line 1,085: Line 1,244:


=={{header|Euphoria}}==
=={{header|Euphoria}}==
<lang euphoria>function map_range(sequence a, sequence b, atom s)
<syntaxhighlight lang="euphoria">function map_range(sequence a, sequence b, atom s)
return b[1]+(s-a[1])*(b[2]-b[1])/(a[2]-a[1])
return b[1]+(s-a[1])*(b[2]-b[1])/(a[2]-a[1])
end function
end function
Line 1,091: Line 1,250:
for i = 0 to 10 do
for i = 0 to 10 do
printf(1, "%2g maps to %4g\n", {i, map_range({0,10},{-1,0},i)})
printf(1, "%2g maps to %4g\n", {i, map_range({0,10},{-1,0},i)})
end for</lang>
end for</syntaxhighlight>


{{out}}
{{out}}
Line 1,106: Line 1,265:
10 maps to 0
10 maps to 0
</pre>
</pre>

=={{header|F#}}==
<syntaxhighlight lang="fsharp">
let map (a1: float) (a2: float) (b1: float) (b2: float) (s: float): float =
b1 + (s - a1) * (b2 - b1) / (a2 - a1)

let xs = [| for i in 0..10 -> map 0.0 10.0 -1.0 0.0 (float i) |]

for x in xs do printfn "%f" x
</syntaxhighlight>


=={{header|Factor}}==
=={{header|Factor}}==
<lang factor>USE: locals
<syntaxhighlight lang="factor">USE: locals
:: map-range ( a1 a2 b1 b2 x -- y )
:: map-range ( a1 a2 b1 b2 x -- y )
x a1 - b2 b1 - * a2 a1 - / b1 + ;</lang>
x a1 - b2 b1 - * a2 a1 - / b1 + ;</syntaxhighlight>
Or:
Or:
<lang factor>USING: locals infix ;
<syntaxhighlight lang="factor">USING: locals infix ;
:: map-range ( a1 a2 b1 b2 x -- y )
:: map-range ( a1 a2 b1 b2 x -- y )
[infix
[infix
b1 + (x - a1) * (b2 - b1) / (a2 - a1)
b1 + (x - a1) * (b2 - b1) / (a2 - a1)
infix] ;</lang>
infix] ;</syntaxhighlight>
Test run:
Test run:
<lang factor>10 iota [| x | 0 10 -1 0 x map-range ] map . ! { -1 -9/10 -4/5 -7/10 -3/5 -1/2 -2/5 -3/10 -1/5 -1/10 }</lang>
<syntaxhighlight lang="factor">10 iota [| x | 0 10 -1 0 x map-range ] map . ! { -1 -9/10 -4/5 -7/10 -3/5 -1/2 -2/5 -3/10 -1/5 -1/10 }</syntaxhighlight>


=={{header|Fantom}}==
=={{header|Fantom}}==


<lang fantom>
<syntaxhighlight lang="fantom">
class FRange
class FRange
{
{
Line 1,157: Line 1,326:
}
}
}
}
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 1,175: Line 1,344:


=={{header|Forth}}==
=={{header|Forth}}==
<lang forth>\ linear interpolation
<syntaxhighlight lang="forth">\ linear interpolation


: lerp ( b2 b1 a2 a1 s -- t )
: lerp ( b2 b1 a2 a1 s -- t )
Line 1,183: Line 1,352:
f+ ;
f+ ;


: test 11 0 do 0e -1e 10e 0e i s>f lerp f. loop ;</lang>
: test 11 0 do 0e -1e 10e 0e i s>f lerp f. loop ;</syntaxhighlight>


There is less stack shuffling if you use origin and range instead of endpoints for intervals. (o = a1, r = a2-a1)
There is less stack shuffling if you use origin and range instead of endpoints for intervals. (o = a1, r = a2-a1)


<lang forth>: lerp ( o2 r2 r1 o1 s -- t ) fswap f- fswap f/ f* f+ ;
<syntaxhighlight lang="forth">: lerp ( o2 r2 r1 o1 s -- t ) fswap f- fswap f/ f* f+ ;


: test 11 0 do -1e 1e 10e 0e i s>f lerp f. loop ;</lang>
: test 11 0 do -1e 1e 10e 0e i s>f lerp f. loop ;</syntaxhighlight>


=={{header|Fortran}}==
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
{{works with|Fortran|90 and later}}
<lang fortran>program Map
<syntaxhighlight lang="fortran">program Map
implicit none
implicit none
Line 1,213: Line 1,382:


end function Maprange
end function Maprange
end program Map</lang>
end program Map</syntaxhighlight>




=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
{{trans|Yabasic}}
{{trans|Yabasic}}
<lang freebasic>Function MapRange(s As Integer, a1 As Integer, a2 As Integer, b1 As Integer, b2 As Integer) As Double
<syntaxhighlight lang="freebasic">Function MapRange(s As Integer, a1 As Integer, a2 As Integer, b1 As Integer, b2 As Integer) As Double
Return b1+(s-a1)*(b2-b1)/(a2-a1)
Return b1+(s-a1)*(b2-b1)/(a2-a1)
End Function
End Function
Line 1,225: Line 1,394:
Print Using "## maps to ##.#"; i; MapRange(i,0,10,-1,0)
Print Using "## maps to ##.#"; i; MapRange(i,0,10,-1,0)
Next i
Next i
Sleep</lang>
Sleep</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,241: Line 1,410:
</pre>
</pre>


=={{header|Frink}}==
Frink can exactly map to rational numbers so the mapping is round-trippable.
<syntaxhighlight lang="frink">mapRange[s, a1, a2, b1, b2] := b1 + (s-a1)(b2-b1)/(a2-a1)

for a = 0 to 10
println["$a\t" + mapRange[a, 0, 10, -1, 0]]</syntaxhighlight>
{{out}}
<pre>
0 -1
1 -9/10 (exactly -0.9)
2 -4/5 (exactly -0.8)
3 -7/10 (exactly -0.7)
4 -3/5 (exactly -0.6)
5 -1/2 (exactly -0.5)
6 -2/5 (exactly -0.4)
7 -3/10 (exactly -0.3)
8 -1/5 (exactly -0.2)
9 -1/10 (exactly -0.1)
10 0
</pre>

Much more impressive, though, is that Frink is a powerful Computer Algebra System (CAS) and can symbolically invert the function so you can map t back to s:

https://frinklang.org/fsp/solve2.fsp?equations=t+%3D+b1+%2B+%28s-a1%29%28b2-b1%29%2F%28a2-a1%29&solveFor=s&f=on&ev=on&sel_a1=S&val_a1=&sel_a2=S&val_a2=&sel_b1=S&val_b1=&sel_b2=S&val_b2=&sel_t=S&val_t=1000+kg&resultAs=

The resulting inverse function is:
<syntaxhighlight lang="frink">inverseMapRange[t, a1, a2, b1, b2] := a1 + a1 b1 (-1 b1 + b2)^-1 + -1 a2 b1 (-1 b1 + b2)^-1 + -1 a1 (-1 b1 + b2)^-1 t + a2 (-1 b1 + b2)^-1 t</syntaxhighlight>

=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"

local fn MapRange( s as double, a1 as double, a2 as double, b1 as double, b2 as double ) as double
end fn = b1+(s-a1)*(b2-b1)/(a2-a1)

NSInteger i

for i = 0 to 10
NSLog( @"%2d maps to %5.1f", i, fn MapRange( i, 0, 10, -1, 0 ) )
next

HandleEvents
</syntaxhighlight>
Output:
<pre>
0 maps to -1.0
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0.0
</pre>

=={{header|GDScript}}==
<syntaxhighlight lang="gdscript">func mapRange(s:float, a1:float, a2:float, b1:float, b2:float) -> float :
return b1 + ((b2-b1)/(a2-a1))*(s-a1)

for i in 11 :
print( "%2d %+.1f" % [i,mapRange(i,0.0,10.0,-1.0,0.0)] )
</syntaxhighlight>

{{out}}
<pre>
0 -1.0
1 -0.9
2 -0.8
3 -0.7
4 -0.6
5 -0.5
6 -0.4
7 -0.3
8 -0.2
9 -0.1
10 +0.0
</pre>


=={{header|Go}}==
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"

local fn MapRange( s as double, a1 as double, a2 as double, b1 as double, b2 as double ) as double
end fn = b1+(s-a1)*(b2-b1)/(a2-a1)

NSInteger i

for i = 0 to 10
NSLog( @"%2d maps to %5.1f", i, fn MapRange( i, 0, 10, -1, 0 ) )
next

HandleEvents
</syntaxhighlight>
Output:
<pre>
0 maps to -1.0
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0.0
</pre>


=={{header|Go}}==
=={{header|Go}}==
'''Basic task'''
'''Basic task'''
<lang go>package main
<syntaxhighlight lang="go">package main


import "fmt"
import "fmt"
Line 1,262: Line 1,542:
fmt.Println(n, "maps to", mapRange(r1, r2, n))
fmt.Println(n, "maps to", mapRange(r1, r2, n))
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,282: Line 1,562:
Second, ", ok" is a Go idiom. It takes advantage of Go's multiple return values and multiple assignment to return a success/failure disposition.
Second, ", ok" is a Go idiom. It takes advantage of Go's multiple return values and multiple assignment to return a success/failure disposition.
In the case of this task, the result t is undefined if the input s is out of range.
In the case of this task, the result t is undefined if the input s is out of range.
<lang go>package main
<syntaxhighlight lang="go">package main


import "fmt"
import "fmt"
Line 1,318: Line 1,598:
}
}
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,332: Line 1,612:


=={{header|Groovy}}==
=={{header|Groovy}}==
<lang groovy>
<syntaxhighlight lang="groovy">
def mapRange(a1, a2, b1, b2, s) {
def mapRange(a1, a2, b1, b2, s) {
b1 + ((s - a1) * (b2 - b1)) / (a2 - a1)
b1 + ((s - a1) * (b2 - b1)) / (a2 - a1)
Line 1,340: Line 1,620:
println(s + " in [0, 10] maps to " + mapRange(0, 10, -1, 0, s) + " in [-1, 0].")
println(s + " in [0, 10] maps to " + mapRange(0, 10, -1, 0, s) + " in [-1, 0].")
}
}
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,358: Line 1,638:
=={{header|Haskell}}==
=={{header|Haskell}}==
Rather than handling only floating point numbers, the mapping function takes any number implementing the <tt>Fractional</tt> typeclass, which in our example also includes exact <tt>Rational</tt> numbers.
Rather than handling only floating point numbers, the mapping function takes any number implementing the <tt>Fractional</tt> typeclass, which in our example also includes exact <tt>Rational</tt> numbers.
<lang haskell>import Data.Ratio
<syntaxhighlight lang="haskell">import Data.Ratio
import Text.Printf (PrintfType, printf)
import Text.Printf (PrintfType, printf)


Line 1,385: Line 1,665:
:: PrintfType r
:: PrintfType r
=> Integer -> Rational -> r
=> Integer -> Rational -> r
prtR n x = printf "%2d -> %s\n" n (show x)</lang>
prtR n x = printf "%2d -> %s\n" n (show x)</syntaxhighlight>
{{out}}
{{out}}
<pre>---------- Floating point ----------
<pre>---------- Floating point ----------
Line 1,414: Line 1,694:
=={{header|Icon}} and {{header|Unicon}}==
=={{header|Icon}} and {{header|Unicon}}==


<syntaxhighlight lang="unicon">
<lang Unicon>
record Range(a, b)
record Range(a, b)


Line 1,438: Line 1,718:
}
}
end
end
</syntaxhighlight>
</lang>


Icon does not permit the type declaration, as Unicon does. For Icon, replace 'remap' with:
Icon does not permit the type declaration, as Unicon does. For Icon, replace 'remap' with:


<syntaxhighlight lang="icon">
<lang Icon>
procedure remap (range1, range2, n)
procedure remap (range1, range2, n)
n *:= 1.0
n *:= 1.0
Line 1,448: Line 1,728:
return range1.a + (n - range2.a) * (range1.b - range1.a) / (range2.b - range2.a)
return range1.a + (n - range2.a) * (range1.b - range1.a) / (range2.b - range2.a)
end
end
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 1,467: Line 1,747:
=={{header|J}}==
=={{header|J}}==


<lang j>maprange=:2 :0
<syntaxhighlight lang="j">maprange=:2 :0
'a1 a2'=.m
'a1 a2'=.m
'b1 b2'=.n
'b1 b2'=.n
b1+((y-a1)*b2-b1)%a2-a1
b1+((y-a1)*b2-b1)%a2-a1
)
)
NB. this version defers all calculations to runtime, but mirrors exactly the task formulation</lang>
NB. this version defers all calculations to runtime, but mirrors exactly the task formulation</syntaxhighlight>


Or
Or


<lang j>maprange=:2 :0
<syntaxhighlight lang="j">maprange=:2 :0
'a1 a2'=.m
'a1 a2'=.m
'b1 b2'=.n
'b1 b2'=.n
b1 + ((b2-b1)%a2-a1) * -&a1
b1 + ((b2-b1)%a2-a1) * -&a1
)
)
NB. this version precomputes the scaling ratio</lang>
NB. this version precomputes the scaling ratio</syntaxhighlight>

Or, more concisely:<syntaxhighlight lang="j">maprange=:{{ ({.n) + (n%&(-/)m) * -&({.m) }}</syntaxhighlight>


Example use:
Example use:


<lang j> 2 4 maprange 5 11 (2.718282 3 3.141592)
<syntaxhighlight lang="j"> 2 4 maprange 5 11 (2.718282 3 3.141592)
7.15485 8 8.42478</lang>
7.15485 8 8.42478</syntaxhighlight>


or
or


<lang j> adjust=:2 4 maprange 5 11 NB. save the derived function as a named entity
<syntaxhighlight lang="j"> adjust=:2 4 maprange 5 11 NB. save the derived function as a named entity
adjust 2.718282 3 3.141592
adjust 2.718282 3 3.141592
7.15485 8 8.42478</lang>
7.15485 8 8.42478</syntaxhighlight>


Required example:
Required example:


<lang j> 0 10 maprange _1 0 i.11
<syntaxhighlight lang="j"> 0 10 maprange _1 0 i.11
_1 _0.9 _0.8 _0.7 _0.6 _0.5 _0.4 _0.3 _0.2 _0.1 0</lang>
_1 _0.9 _0.8 _0.7 _0.6 _0.5 _0.4 _0.3 _0.2 _0.1 0</syntaxhighlight>


=={{header|Java}}==
=={{header|Java}}==
<lang java>public class Range {
<syntaxhighlight lang="java">public class Range {
public static void main(String[] args){
public static void main(String[] args){
for(float s = 0;s <= 10; s++){
for(float s = 0;s <= 10; s++){
Line 1,511: Line 1,793:
return b1 + ((s - a1)*(b2 - b1))/(a2 - a1);
return b1 + ((s - a1)*(b2 - b1))/(a2 - a1);
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>0.0 in [0, 10] maps to -1.0 in [-1, 0].
<pre>0.0 in [0, 10] maps to -1.0 in [-1, 0].
Line 1,528: Line 1,810:
=={{header|JavaScript}}==
=={{header|JavaScript}}==
===ES5===
===ES5===
<lang JavaScript>// Javascript doesn't have built-in support for ranges
<syntaxhighlight lang="javascript">// Javascript doesn't have built-in support for ranges
// Insted we use arrays of two elements to represent ranges
// Insted we use arrays of two elements to represent ranges
var mapRange = function(from, to, s) {
var mapRange = function(from, to, s) {
Line 1,539: Line 1,821:
}
}


console.log(range);</lang>
console.log(range);</syntaxhighlight>
{{out}}
{{out}}
<pre>[-1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.30000000000000004, -0.19999999999999996, -0.09999999999999998, 0]</pre>
<pre>[-1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.30000000000000004, -0.19999999999999996, -0.09999999999999998, 0]</pre>
Line 1,546: Line 1,828:
Here we will use the [https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map ECMAScript 5 support for map] and the [http://underscorejs.org/#range _.range] function from Underscore.js.
Here we will use the [https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map ECMAScript 5 support for map] and the [http://underscorejs.org/#range _.range] function from Underscore.js.
{{libheader|Underscore.js}}
{{libheader|Underscore.js}}
<lang JavaScript>var mapRange = function(from, to, s) {
<syntaxhighlight lang="javascript">var mapRange = function(from, to, s) {
// mapRange expects ranges generated by _.range
// mapRange expects ranges generated by _.range
var a1 = from[0];
var a1 = from[0];
Line 1,564: Line 1,846:
});
});


console.log(fromRange);</lang>
console.log(fromRange);</syntaxhighlight>
{{out}}
{{out}}
<pre>[-1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.30000000000000004, -0.19999999999999996, -0.09999999999999998, 0]</pre>
<pre>[-1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.30000000000000004, -0.19999999999999996, -0.09999999999999998, 0]</pre>
Line 1,571: Line 1,853:


Composing a solution from generic abstractions:
Composing a solution from generic abstractions:
<lang javascript>(() => {
<syntaxhighlight lang="javascript">(() => {
'use strict';
'use strict';


Line 1,699: Line 1,981:
// MAIN ---
// MAIN ---
return main();
return main();
})();</lang>
})();</syntaxhighlight>
{{Out}}
{{Out}}
<pre> 0 -> -1 = -1/1
<pre> 0 -> -1 = -1/1
Line 1,716: Line 1,998:
In jq, it is generally preferable to define functions as parameterized filters. In the present case,
In jq, it is generally preferable to define functions as parameterized filters. In the present case,
since the task calls for defining a map, the signature maprange(a;b), where a and b are the two ranges, is appropriate.
since the task calls for defining a map, the signature maprange(a;b), where a and b are the two ranges, is appropriate.
<lang jq># The input is the value to be mapped.
<syntaxhighlight lang="jq"># The input is the value to be mapped.
# The ranges, a and b, should each be an array defining the
# The ranges, a and b, should each be an array defining the
# left-most and right-most points of the range.
# left-most and right-most points of the range.
def maprange(a; b):
def maprange(a; b):
b[0] + (((. - a[0]) * (b[1] - b[0])) / (a[1] - a[0])) ;</lang>
b[0] + (((. - a[0]) * (b[1] - b[0])) / (a[1] - a[0])) ;</syntaxhighlight>
'''Example 1''': a single value
'''Example 1''': a single value
6 | maprange([0,10]; [-1, 0])
6 | maprange([0,10]; [-1, 0])
Line 1,727: Line 2,009:


'''Example 2''': a stream of values
'''Example 2''': a stream of values
<lang jq>range(0;11) | maprange([0,10]; [-1, 0])</lang>
<syntaxhighlight lang="jq">range(0;11) | maprange([0,10]; [-1, 0])</syntaxhighlight>
produces:
produces:
-1
-1
Line 1,742: Line 2,024:
====Extra credit====
====Extra credit====
To avoid repeating the same arithmetic, we shall define a filter that handles an array of values all at once, using an inner function and map/1:
To avoid repeating the same arithmetic, we shall define a filter that handles an array of values all at once, using an inner function and map/1:
<lang jq>def maprange_array(a; b):
<syntaxhighlight lang="jq">def maprange_array(a; b):
def _helper(a0; b0; factor): b0 + (. - a0) * factor;
def _helper(a0; b0; factor): b0 + (. - a0) * factor;


a[0] as $a | b[0] as $b | ((b[1] - b[0]) / (a[1] - a[0])) as $factor
a[0] as $a | b[0] as $b | ((b[1] - b[0]) / (a[1] - a[0])) as $factor
| map(_helper( $a; $b; $factor) );</lang>
| map(_helper( $a; $b; $factor) );</syntaxhighlight>
'''Example''':
'''Example''':
[range(0;11)] | maprange_array([0,10]; [-1, 0])
[range(0;11)] | maprange_array([0,10]; [-1, 0])
Line 1,753: Line 2,035:
{{works with|Julia|0.6}}
{{works with|Julia|0.6}}


<lang julia>function maprange(s, a, b)
<syntaxhighlight lang="julia">function maprange(s, a, b)
a₁, a₂ = minimum(a), maximum(a)
a₁, a₂ = minimum(a), maximum(a)
b₁, b₂ = minimum(b), maximum(b)
b₁, b₂ = minimum(b), maximum(b)
Line 1,760: Line 2,042:


@show maprange(6, 1:10, -1:0)
@show maprange(6, 1:10, -1:0)
@show maprange(0:10, 0:10, -1:0)</lang>
@show maprange(0:10, 0:10, -1:0)</syntaxhighlight>


{{out}}
{{out}}
Line 1,767: Line 2,049:


=={{header|K}}==
=={{header|K}}==
<lang K> f:{[a1;a2;b1;b2;s] b1+(s-a1)*(b2-b1)%(a2-a1)}
<syntaxhighlight lang="k"> f:{[a1;a2;b1;b2;s] b1+(s-a1)*(b2-b1)%(a2-a1)}


+(a; f[0;10;-1;0]'a:!11)
+(a; f[0;10;-1;0]'a:!11)
Line 1,780: Line 2,062:
(8;-0.2)
(8;-0.2)
(9;-0.1)
(9;-0.1)
(10;0.0))</lang>
(10;0.0))</syntaxhighlight>


=={{header|Kotlin}}==
=={{header|Kotlin}}==
<lang scala>// version 1.0.6
<syntaxhighlight lang="scala">// version 1.0.6


class FloatRange(override val start: Float, override val endInclusive: Float) : ClosedRange<Float>
class FloatRange(override val start: Float, override val endInclusive: Float) : ClosedRange<Float>
Line 1,798: Line 2,080:
println(String.format("%2d maps to %+4.2f", i, mappedValue))
println(String.format("%2d maps to %+4.2f", i, mappedValue))
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 1,816: Line 2,098:


=={{header|Lambdatalk}}==
=={{header|Lambdatalk}}==
<lang scheme>
<syntaxhighlight lang="scheme">
{def maprange
{def maprange
{lambda {:a0 :a1 :b0 :b1 :s}
{lambda {:a0 :a1 :b0 :b1 :s}
Line 1,838: Line 2,120:
9 maps to -0.09999999999999998
9 maps to -0.09999999999999998
10 maps to 0
10 maps to 0
</syntaxhighlight>
</lang>


=={{header|Lasso}}==
=={{header|Lasso}}==
<lang Lasso>define map_range(
<syntaxhighlight lang="lasso">define map_range(
a1,
a1,
a2,
a2,
Line 1,855: Line 2,137:
'<br />'
'<br />'


^}'</lang>
^}'</syntaxhighlight>
{{out}}
{{out}}
<pre>0: -1.0
<pre>0: -1.0
Line 1,870: Line 2,152:


=={{header|Liberty BASIC}}==
=={{header|Liberty BASIC}}==
<lang liberty basic>For i = 0 To 10
<syntaxhighlight lang="liberty basic">For i = 0 To 10
Print "f(";i;") maps to ";mapToRange(i, 0, 10, -1, 0)
Print "f(";i;") maps to ";mapToRange(i, 0, 10, -1, 0)
Next i
Next i
Line 1,878: Line 2,160:
mapToRange = (((value - inputMin) * (outputMax - outputMin)) / (inputMax - inputMin)) + outputMin
mapToRange = (((value - inputMin) * (outputMax - outputMin)) / (inputMax - inputMin)) + outputMin
End Function
End Function
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>f(0) maps to -1
<pre>f(0) maps to -1
Line 1,893: Line 2,175:


=={{header|Logo}}==
=={{header|Logo}}==
<lang logo>to interpolate :s :a1 :a2 :b1 :b2
<syntaxhighlight lang="logo">to interpolate :s :a1 :a2 :b1 :b2
output (:s-:a1) / (:a2-:a1) * (:b2-:b1) + :b1
output (:s-:a1) / (:a2-:a1) * (:b2-:b1) + :b1
end
end


for [i 0 10] [print interpolate :i 0 10 -1 0]</lang>
for [i 0 10] [print interpolate :i 0 10 -1 0]</syntaxhighlight>


=={{header|Lua}}==
=={{header|Lua}}==
<lang lua>function map_range( a1, a2, b1, b2, s )
<syntaxhighlight lang="lua">function map_range( a1, a2, b1, b2, s )
return b1 + (s-a1)*(b2-b1)/(a2-a1)
return b1 + (s-a1)*(b2-b1)/(a2-a1)
end
end
Line 1,906: Line 2,188:
for i = 0, 10 do
for i = 0, 10 do
print( string.format( "f(%d) = %f", i, map_range( 0, 10, -1, 0, i ) ) )
print( string.format( "f(%d) = %f", i, map_range( 0, 10, -1, 0, i ) ) )
end</lang>
end</syntaxhighlight>

=={{header|M2000 Interpreter}}==

=== Using Class ===
<syntaxhighlight lang="m2000 interpreter">
module MapRange {
class Map {
private:
a, b, f
public:
value (x){
=.b+(x-.a)*.f
}
class:
module Map (.a,a2,.b,b2) {
if a2-.a=0 then error "wrong parameters"
.f<=(b2-.b)/(a2-.a)
}
}
m1=Map(0,10, -1, 0)
for i=0 to 10
Print i," maps to ";m1(i)
next
}
MapRange
</syntaxhighlight>

=== Using Lambda ===

<syntaxhighlight lang="m2000 interpreter">
module MapRange {
Map=lambda (a,a2,b,b2) -> {
if a2-a=0 then error "wrong parameters"
f=(b2-b)/(a2-a)
=lambda a,b,f (x)->b+(x-a)*f
}
m1=Map(0,10, -1, 0)
for i=0 to 10
Print i," maps to ";m1(i)
next
}
MapRange
</syntaxhighlight>

Same output for both versions

{{out}}
<pre>
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0
</pre>


=={{header|Maple}}==
=={{header|Maple}}==
<syntaxhighlight lang="maple">
<lang Maple>
Map:=proc(a1,a2,b1,b2,s);
Map:=proc(a1,a2,b1,b2,s);
return (b1+((s-a1)*(b2-b1)/(a2-a1)));
return (b1+((s-a1)*(b2-b1)/(a2-a1)));
Line 1,918: Line 2,261:
printf("%a\n",Map(0,10,-1,0,i));
printf("%a\n",Map(0,10,-1,0,i));
end do;
end do;
</syntaxhighlight>
</lang>


=={{header|Mathematica}}/{{header|Wolfram Language}}==
=={{header|Mathematica}}/{{header|Wolfram Language}}==
Such a function is already built in
Such a function is already built in
<lang Mathematica>Rescale[#,{0,10},{-1,0}]&/@Range[0,10]</lang>
<syntaxhighlight lang="mathematica">Rescale[#,{0,10},{-1,0}]&/@Range[0,10]</syntaxhighlight>
{{out}}
{{out}}
<pre>{-1., -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.}</pre>
<pre>{-1., -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.}</pre>


=={{header|Maxima}}==
=={{header|Maxima}}==
<lang maxima>maprange(a, b, c, d) := buildq([e: ratsimp(('x - a)*(d - c)/(b - a) + c)],
<syntaxhighlight lang="maxima">maprange(a, b, c, d) := buildq([e: ratsimp(('x - a)*(d - c)/(b - a) + c)],
lambda([x], e))$
lambda([x], e))$


f: maprange(0, 10, -1, 0);</lang>
f: maprange(0, 10, -1, 0);</syntaxhighlight>


=={{header|Nemerle}}==
=={{header|Nemerle}}==
<lang Nemerle>using System;
<syntaxhighlight lang="nemerle">using System;
using System.Console;
using System.Console;


Line 1,950: Line 2,293:
WriteLine("{0, 2:f0} maps to {1:f1}", i, Maprange((0.0, 10.0), (-1.0, 0.0), i));
WriteLine("{0, 2:f0} maps to {1:f1}", i, Maprange((0.0, 10.0), (-1.0, 0.0), i));
}
}
}</lang>
}</syntaxhighlight>


=={{header|NetRexx}}==
=={{header|NetRexx}}==
<lang netrexx>/* NetRexx */
<syntaxhighlight lang="netrexx">/* NetRexx */
options replace format comments java crossref savelog symbols nobinary
options replace format comments java crossref savelog symbols nobinary


Line 1,973: Line 2,316:
t_ = b1 + ((s_ - a1) * (b2 - b1) / (a2 - a1))
t_ = b1 + ((s_ - a1) * (b2 - b1) / (a2 - a1))
return t_
return t_
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,994: Line 2,337:
{{trans|Python}}
{{trans|Python}}


<lang nim>import strformat
<syntaxhighlight lang="nim">import strformat


type FloatRange = tuple[s, e: float]
type FloatRange = tuple[s, e: float]
Line 2,003: Line 2,346:
for i in 0..10:
for i in 0..10:
let m = mapRange((0.0,10.0), (-1.0, 0.0), float(i))
let m = mapRange((0.0,10.0), (-1.0, 0.0), float(i))
echo &"{i:>2} maps to {m:4.1f}"</lang>
echo &"{i:>2} maps to {m:4.1f}"</syntaxhighlight>


{{out}}
{{out}}
Line 2,019: Line 2,362:


=={{header|Objeck}}==
=={{header|Objeck}}==
<lang objeck>
<syntaxhighlight lang="objeck">
bundle Default {
bundle Default {
class Range {
class Range {
Line 2,034: Line 2,377:
}
}
}
}
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 2,054: Line 2,397:
=={{header|OCaml}}==
=={{header|OCaml}}==


<lang ocaml>let map_range (a1, a2) (b1, b2) s =
<syntaxhighlight lang="ocaml">let map_range (a1, a2) (b1, b2) s =
b1 +. ((s -. a1) *. (b2 -. b1) /. (a2 -. a1))
b1 +. ((s -. a1) *. (b2 -. b1) /. (a2 -. a1))
Line 2,061: Line 2,404:
for i = 0 to 10 do
for i = 0 to 10 do
Printf.printf "f(%d) = %g\n" i (map_range (0.0, 10.0) (-1.0, 0.0) (float i))
Printf.printf "f(%d) = %g\n" i (map_range (0.0, 10.0) (-1.0, 0.0) (float i))
done</lang>
done</syntaxhighlight>


{{out}}
{{out}}
Line 2,079: Line 2,422:
If range mapping is used in a heavy computational task we can reduce the number of calculations made using partial application and [[currying]]:
If range mapping is used in a heavy computational task we can reduce the number of calculations made using partial application and [[currying]]:


<lang ocaml>let map_range (a1, a2) (b1, b2) =
<syntaxhighlight lang="ocaml">let map_range (a1, a2) (b1, b2) =
let v = (b2 -. b1) /. (a2 -. a1) in
let v = (b2 -. b1) /. (a2 -. a1) in
function s ->
function s ->
Line 2,089: Line 2,432:
for i = 0 to 10 do
for i = 0 to 10 do
Printf.printf "f(%d) = %g\n" i (p (float i))
Printf.printf "f(%d) = %g\n" i (p (float i))
done</lang>
done</syntaxhighlight>


=={{header|Oforth}}==
=={{header|Oforth}}==


<lang Oforth>: mapRange(p1, p2, s)
<syntaxhighlight lang="oforth">: mapRange(p1, p2, s)
s p1 first - p2 second p2 first - * p1 second p1 first - asFloat /
s p1 first - p2 second p2 first - * p1 second p1 first - asFloat /
p2 first + ;</lang>
p2 first + ;</syntaxhighlight>


{{out}}
{{out}}
Line 2,106: Line 2,449:
=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
Usage (e.g.): map([1,10],[0,5],8.)
Usage (e.g.): map([1,10],[0,5],8.)
<lang parigp>map(r1,r2,x)=r2[1]+(x-r1[1])*(r2[2]-r2[1])/(r1[2]-r1[1])</lang>
<syntaxhighlight lang="parigp">map(r1,r2,x)=r2[1]+(x-r1[1])*(r2[2]-r2[1])/(r1[2]-r1[1])</syntaxhighlight>


=={{header|Pascal}}==
=={{header|Pascal}}==
<lang pascal>Program Map(output);
<syntaxhighlight lang="pascal">Program Map(output);


function MapRange(fromRange, toRange: array of real; value: real): real;
function MapRange(fromRange, toRange: array of real; value: real): real;
Line 2,121: Line 2,464:
for i := 0 to 10 do
for i := 0 to 10 do
writeln (i, ' maps to: ', MapRange([0.0, 10.0], [-1.0, 0.0], i):4:2);
writeln (i, ' maps to: ', MapRange([0.0, 10.0], [-1.0, 0.0], i):4:2);
end.</lang>
end.</syntaxhighlight>
{{out}}
{{out}}
<pre>:> ./MapRange
<pre>:> ./MapRange
Line 2,149: Line 2,492:


Output as above.
Output as above.
<lang pascal>Program Map(output);
<syntaxhighlight lang="pascal">Program Map(output);


type
type
Line 2,204: Line 2,547:
MapRecRange(value,mr):10:6);
MapRecRange(value,mr):10:6);
end;
end;
end.</lang>
end.</syntaxhighlight>


=={{header|Perl}}==
=={{header|Perl}}==
<lang Perl>#!/usr/bin/perl -w
<syntaxhighlight lang="perl">#!/usr/bin/perl -w
use strict ;
use strict ;


Line 2,219: Line 2,562:
my @interval = ( -1 , 0 ) ;
my @interval = ( -1 , 0 ) ;
print "The mapped value for $_ is " . mapValue( \@numbers , \@interval , $_ ) . " !\n" foreach @numbers ;
print "The mapped value for $_ is " . mapValue( \@numbers , \@interval , $_ ) . " !\n" foreach @numbers ;
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<PRE>The mapped value for 0 is -1 !
<PRE>The mapped value for 0 is -1 !
Line 2,235: Line 2,578:


=={{header|Phix}}==
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function MapRange(atom s, a1, a2, b1, b2)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
return b1+(s-a1)*(b2-b1)/(a2-a1)
<span style="color: #008080;">function</span> <span style="color: #000000;">map_range</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b2</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">b1</span><span style="color: #0000FF;">+(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">-</span><span style="color: #000000;">a1</span><span style="color: #0000FF;">)*(</span><span style="color: #000000;">b2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">b1</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">a2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">a1</span><span style="color: #0000FF;">)</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
for i=0 to 10 by 2 do
printf(1,"%2d : %g\n",{i,MapRange(i,0,10,-1,0)})
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">by</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
end for</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%2d : %g\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">map_range</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 2,253: Line 2,599:


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
<lang PicoLisp>(scl 1)
<syntaxhighlight lang="picolisp">(scl 1)


(de mapRange (Val A1 A2 B1 B2)
(de mapRange (Val A1 A2 B1 B2)
Line 2,261: Line 2,607:
(for Val (range 0 10.0 1.0)
(for Val (range 0 10.0 1.0)
(prinl
(prinl
(format (mapRange Val 0 10.0 -1.0 0) *Scl) ) )</lang>
(format (mapRange Val 0 10.0 -1.0 0) *Scl) ) )</syntaxhighlight>
{{out}}
{{out}}
<pre>-1.0
<pre>-1.0
Line 2,276: Line 2,622:


=={{header|PL/I}}==
=={{header|PL/I}}==
<lang pli>
<syntaxhighlight lang="pli">
map: procedure options (main); /* 24/11/2011 */
map: procedure options (main); /* 24/11/2011 */
declare (a1, a2, b1, b2) float;
declare (a1, a2, b1, b2) float;
Line 2,290: Line 2,636:
end map;
end map;
end map;
end map;
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 2,309: Line 2,655:


=={{header|PowerShell}}==
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Group-Range
function Group-Range
{
{
Line 2,346: Line 2,692:
}
}
}
}
</syntaxhighlight>
</lang>
<syntaxhighlight lang="powershell">
<lang PowerShell>
0..10 | Group-Range (0,10) (-1,0)
0..10 | Group-Range (0,10) (-1,0)
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
<pre>
<pre>
Line 2,368: Line 2,714:


=={{header|PureBasic}}==
=={{header|PureBasic}}==
<lang purebasic>Structure RR
<syntaxhighlight lang="purebasic">Structure RR
a.f
a.f
b.f
b.f
Line 2,390: Line 2,736:
PrintN(RSet(Str(i),2)+" maps to "+StrF(MapRange(@Range1, @Range2, i),1))
PrintN(RSet(Str(i),2)+" maps to "+StrF(MapRange(@Range1, @Range2, i),1))
Next
Next
EndIf</lang>
EndIf</syntaxhighlight>
<pre> 0 maps to -1.0
<pre> 0 maps to -1.0
1 maps to -0.9
1 maps to -0.9
Line 2,404: Line 2,750:


=={{header|Python}}==
=={{header|Python}}==
<lang python>>>> def maprange( a, b, s):
<syntaxhighlight lang="python">>>> def maprange( a, b, s):
(a1, a2), (b1, b2) = a, b
(a1, a2), (b1, b2) = a, b
return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
Line 2,422: Line 2,768:
8 maps to -0.2
8 maps to -0.2
9 maps to -0.1
9 maps to -0.1
10 maps to 0</lang>
10 maps to 0</syntaxhighlight>


Because of Pythons strict, dynamic, typing rules for numbers the same function can give answers as fractions:
Because of Pythons strict, dynamic, typing rules for numbers the same function can give answers as fractions:
<lang python>>>> from fractions import Fraction
<syntaxhighlight lang="python">>>> from fractions import Fraction
>>> for s in range(11):
>>> for s in range(11):
print("%2g maps to %s" % (s, maprange( (0, 10), (-1, 0), Fraction(s))))
print("%2g maps to %s" % (s, maprange( (0, 10), (-1, 0), Fraction(s))))
Line 2,441: Line 2,787:
9 maps to -1/10
9 maps to -1/10
10 maps to 0
10 maps to 0
>>> </lang>
>>> </syntaxhighlight>

=={{header|Quackery}}==

As Quackery does not support reals (or floating point), the function takes the argument s as a decimal string, and returns the result, t as a rational number.

<syntaxhighlight lang="Quackery"> [ $ "bigrat.qky" loadfile ] now!

[ do over -
2swap
do over -
unrot
dip [ $->v drop ]
n->v v-
rot n->v v/
rot n->v v*
rot n->v v+ ] is maprange ( $ [ [ --> n/d )

$ "0 1 2 3 4 5 6 7 8 9 10"
nest$
witheach
[ dup echo$ say " maps to "
' [ 0 10 ] ' [ -1 0 ] maprange
7 point$ echo$ cr ]</syntaxhighlight>

{{out}}

<pre>0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0</pre>

=={{header|R}}==
=={{header|R}}==
<lang R>tRange <- function(aRange, bRange, s)
<syntaxhighlight lang="rsplus">tRange <- function(aRange, bRange, s)
{
{
#Guard clauses. We could write some proper error messages, but this is all we really need.
#Guard clauses. We could write some proper error messages, but this is all we really need.
Line 2,451: Line 2,835:
bRange[1] + ((s - aRange[1]) * (bRange[2] - bRange[1])) / (aRange[2] - aRange[1])
bRange[1] + ((s - aRange[1]) * (bRange[2] - bRange[1])) / (aRange[2] - aRange[1])
}
}
data.frame(s = 0:10, t = sapply(0:10, tRange, aRange = c(0, 10), bRange = c(-1, 0)))</lang>
data.frame(s = 0:10, t = sapply(0:10, tRange, aRange = c(0, 10), bRange = c(-1, 0)))</syntaxhighlight>
{{out}}
{{out}}
<pre> s t
<pre> s t
Line 2,468: Line 2,852:
=={{header|Racket}}==
=={{header|Racket}}==


<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
#lang racket


Line 2,479: Line 2,863:
(define map (make-range-map 0 10 -1 0))
(define map (make-range-map 0 10 -1 0))
(for ([i (in-range 0 11)]) (printf "~a --> ~a\n" i (map i)))
(for ([i (in-range 0 11)]) (printf "~a --> ~a\n" i (map i)))
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 2,499: Line 2,883:
(formerly Perl 6)
(formerly Perl 6)
Return a closure that does the mapping without have to supply the ranges every time.
Return a closure that does the mapping without have to supply the ranges every time.
<lang perl6>sub getmapper(Range $a, Range $b) {
<syntaxhighlight lang="raku" line>sub getmapper(Range $a, Range $b) {
my ($a1, $a2) = $a.bounds;
my ($a1, $a2) = $a.bounds;
my ($b1, $b2) = $b.bounds;
my ($b1, $b2) = $b.bounds;
Line 2,506: Line 2,890:


my &mapper = getmapper(0 .. 10, -1 .. 0);
my &mapper = getmapper(0 .. 10, -1 .. 0);
for ^11 -> $x {say "$x maps to &mapper($x)"}</lang>
for ^11 -> $x {say "$x maps to &mapper($x)"}</syntaxhighlight>
{{out}}
{{out}}
<pre>0 maps to -1
<pre>0 maps to -1
Line 2,521: Line 2,905:


=={{header|ReScript}}==
=={{header|ReScript}}==
<lang rescript>let map_range = ((a1, a2), (b1, b2), s) => {
<syntaxhighlight lang="rescript">let map_range = ((a1, a2), (b1, b2), s) => {
b1 +. ((s -. a1) *. (b2 -. b1) /. (a2 -. a1))
b1 +. ((s -. a1) *. (b2 -. b1) /. (a2 -. a1))
}
}
Line 2,530: Line 2,914:
Js.log("f(" ++ Js.String.make(i) ++ ") = " ++
Js.log("f(" ++ Js.String.make(i) ++ ") = " ++
Js.String.make(map_range((0.0, 10.0), (-1.0, 0.0), float(i))))
Js.String.make(map_range((0.0, 10.0), (-1.0, 0.0), float(i))))
}</lang>
}</syntaxhighlight>


<lang html><!DOCTYPE html>
<syntaxhighlight lang="html"><!DOCTYPE html>
<html>
<html>
<head>
<head>
Line 2,546: Line 2,930:


</body>
</body>
</html></lang>
</html></syntaxhighlight>


{{out}}
{{out}}
Line 2,574: Line 2,958:


===version 1===
===version 1===
<lang rexx>/*REXX program maps and displays a range of numbers from one range to another range.*/
<syntaxhighlight lang="rexx">/*REXX program maps and displays a range of numbers from one range to another range.*/
rangeA = 0 10 /*or: rangeA = ' 0 10 ' */
rangeA = 0 10 /*or: rangeA = ' 0 10 ' */
rangeB = -1 0 /*or: rangeB = " -1 0 " */
rangeB = -1 0 /*or: rangeB = " -1 0 " */
Line 2,584: Line 2,968:
exit /*stick a fork in it, we're done.*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
mapR: procedure; parse arg a1 a2,b1 b2,s;$=b1+(s-a1)*(b2-b1)/(a2-a1);return left('',$>=0)$</lang>
mapR: procedure; parse arg a1 a2,b1 b2,s;$=b1+(s-a1)*(b2-b1)/(a2-a1);return left('',$>=0)$</syntaxhighlight>
{{out|output}}
{{out|output}}
<pre>
<pre>
Line 2,604: Line 2,988:


Note that this REXX version also uses a different &nbsp; '''rangeA''' &nbsp; numbers &nbsp; (they are reversed).
Note that this REXX version also uses a different &nbsp; '''rangeA''' &nbsp; numbers &nbsp; (they are reversed).
<lang rexx>/*REXX program maps and displays a range of numbers from one range to another range.*/
<syntaxhighlight lang="rexx">/*REXX program maps and displays a range of numbers from one range to another range.*/
rangeA = 10 0 /*or: rangeA = ' 0 10 ' */
rangeA = 10 0 /*or: rangeA = ' 0 10 ' */
rangeB = -1 0 /*or: rangeB = " -1 0 " */
rangeB = -1 0 /*or: rangeB = " -1 0 " */
Line 2,614: Line 2,998:
exit /*stick a fork in it, we're done.*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
mapR: procedure; parse arg a1 a2,b1 b2,s;$=b1+(s-a1)*(b2-b1)/(a2-a1);return left('',$>=0)$</lang>
mapR: procedure; parse arg a1 a2,b1 b2,s;$=b1+(s-a1)*(b2-b1)/(a2-a1);return left('',$>=0)$</syntaxhighlight>
{{out|output}}
{{out|output}}
<pre>
<pre>
Line 2,642: Line 3,026:
===version 3===
===version 3===
This REXX version used a function that calculates and also displays the range mapping.
This REXX version used a function that calculates and also displays the range mapping.
<lang rexx>/*REXX program maps and displays a range of numbers from one range to another range.*/
<syntaxhighlight lang="rexx">/*REXX program maps and displays a range of numbers from one range to another range.*/
rangeA = 0 10
rangeA = 0 10
rangeB = -1 0
rangeB = -1 0
Line 2,654: Line 3,038:
say right(s, 9) ' maps to' left('', t>=0) t
say right(s, 9) ' maps to' left('', t>=0) t
end /*s*/
end /*s*/
return /* [↑] LEFT··· aligns non─negative #'s*/</lang>
return /* [↑] LEFT··· aligns non─negative #'s*/</syntaxhighlight>
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}} <br><br>
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}} <br><br>


===Version 4===
===Version 4===
<lang rexx>/*REXX program maps a number from one range to another range. */
<syntaxhighlight lang="rexx">/*REXX program maps a number from one range to another range. */
/* 31.10.2013 Walter Pachl */
/* 31.10.2013 Walter Pachl */
/* 'translated' from an older version 1 without using Procedure */
/* 'translated' from an older version 1 without using Procedure */
Line 2,667: Line 3,051:
/*──────────────────────────────────MAPRANGE subroutine─────────────────*/
/*──────────────────────────────────MAPRANGE subroutine─────────────────*/
mapRange: return arg(3)+(arg(5)-arg(1))*(arg(4)-arg(3))/(arg(2)-arg(1))
mapRange: return arg(3)+(arg(5)-arg(1))*(arg(4)-arg(3))/(arg(2)-arg(1))
/* Arguments are arg a1,a2,b1,b2,x */</lang>
/* Arguments are arg a1,a2,b1,b2,x */</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 2,684: Line 3,068:


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
# Project : Map range
# Project : Map range


Line 2,698: Line 3,082:
func maprange(al, bl, s)
func maprange(al, bl, s)
return bl + (s - al) * (bh - bl) / (ah - al)
return bl + (s - al) * (bh - bl) / (ah - al)
</syntaxhighlight>
</lang>
Output:
Output:
<pre>
<pre>
Line 2,712: Line 3,096:
9 maps to -0.1
9 maps to -0.1
10 maps to 0
10 maps to 0
</pre>

=={{header|RPL}}==
Ranges are entered as complex numbers to ease input and shorten code
{{works with|Halcyon Calc|4.2.7}}
{| class="wikitable"
! RPL code
! Comment
|-
|
≪ → ra rb s
≪ rb ra - DUP RE SWAP IM /
s ra RE - * rb RE +
≫ ≫ 'MAP' STO
|
''( (a1, a2) (b1, b2) s -- t )''
Get (b2 - b1)/(a2 - a1)
Multiply by (s - a1) and add b1
|}
{{in}}
<pre>
(0,10) (-1,0) 0 MAP
(0,10) (-1,0) 4 MAP
(0,10) (-1,0) 10 MAP
</pre>
{{out}}
<pre>
3: -1
2: -0.6
1: 0
</pre>
===Basic RPL code===
No specific data structure, no local variable, full stack calculation. Shorter, but less practical in use and difficult to read.
≪ SWAP 3 PICK -
SWAP 5 PICK - *
ROT 4 ROLL - / +
≫ 'MAP' STO
{{in}}
<pre>
0 10 -1 0 0 MAP
0 10 -1 0 4 MAP
0 10 -1 0 10 MAP
</pre>
{{out}}
<pre>
3: -1
2: -0.6
1: 0
</pre>
</pre>


=={{header|Ruby}}==
=={{header|Ruby}}==
<lang ruby>def map_range(a, b, s)
<syntaxhighlight lang="ruby">def map_range(a, b, s)
af, al, bf, bl = a.first, a.last, b.first, b.last
af, al, bf, bl = a.first, a.last, b.first, b.last
bf + (s - af)*(bl - bf).quo(al - af)
bf + (s - af)*(bl - bf).quo(al - af)
end
end


(0..10).each{|s| puts "%s maps to %g" % [s, map_range(0..10, -1..0, s)]}</lang>
(0..10).each{|s| puts "%s maps to %g" % [s, map_range(0..10, -1..0, s)]}</syntaxhighlight>


Numeric#quo does floating point division.
Numeric#quo does floating point division.
Line 2,739: Line 3,172:


To use rational arithmetic, delete <code>s *= 1.0</code> and either <code>require 'rational'</code>, or use Ruby 1.9 (which has Rational in the core library).
To use rational arithmetic, delete <code>s *= 1.0</code> and either <code>require 'rational'</code>, or use Ruby 1.9 (which has Rational in the core library).
<lang ruby>(0..10).each do |s|
<syntaxhighlight lang="ruby">(0..10).each do |s|
puts "%s maps to %s" % [s, map_range(0..10, -1..0, s)]
puts "%s maps to %s" % [s, map_range(0..10, -1..0, s)]
end</lang>
end</syntaxhighlight>


{{out}} using rational arithmetic:
{{out}} using rational arithmetic:
Line 2,759: Line 3,192:


=={{header|Rust}}==
=={{header|Rust}}==
<lang rust>use std::f64;
<syntaxhighlight lang="rust">use std::ops::{Add, Sub, Mul, Div};


fn map_range(from_range: (f64, f64), to_range: (f64, f64), s: f64) -> f64 {
fn map_range<T: Copy>(from_range: (T, T), to_range: (T, T), s: T) -> T
where T: Add<T, Output=T> +
Sub<T, Output=T> +
Mul<T, Output=T> +
Div<T, Output=T>
{
to_range.0 + (s - from_range.0) * (to_range.1 - to_range.0) / (from_range.1 - from_range.0)
to_range.0 + (s - from_range.0) * (to_range.1 - to_range.0) / (from_range.1 - from_range.0)
}
}
Line 2,771: Line 3,209:
.collect::<Vec<f64>>();
.collect::<Vec<f64>>();
print!("{:?}", result);
print!("{:?}", result);
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 2,778: Line 3,216:


=={{header|Scala}}==
=={{header|Scala}}==
<lang scala>def mapRange(a1:Double, a2:Double, b1:Double, b2:Double, x:Double):Double=b1+(x-a1)*(b2-b1)/(a2-a1)
<syntaxhighlight lang="scala">def mapRange(a1:Double, a2:Double, b1:Double, b2:Double, x:Double):Double=b1+(x-a1)*(b2-b1)/(a2-a1)


for(i <- 0 to 10)
for(i <- 0 to 10)
println("%2d in [0, 10] maps to %5.2f in [-1, 0]".format(i, mapRange(0,10, -1,0, i)))</lang>
println("%2d in [0, 10] maps to %5.2f in [-1, 0]".format(i, mapRange(0,10, -1,0, i)))</syntaxhighlight>
{{out}}
{{out}}
<pre> 0 in [0, 10] maps to -1,00 in [-1, 0]
<pre> 0 in [0, 10] maps to -1,00 in [-1, 0]
Line 2,796: Line 3,234:


=={{header|Seed7}}==
=={{header|Seed7}}==
<lang seed7>$ include "seed7_05.s7i";
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "float.s7i";
include "float.s7i";


Line 2,810: Line 3,248:
writeln("f(" <& number <& ") = " <& mapRange(0.0, 10.0, -1.0, 0.0, flt(number)) digits 1);
writeln("f(" <& number <& ") = " <& mapRange(0.0, 10.0, -1.0, 0.0, flt(number)) digits 1);
end for;
end for;
end func;</lang>
end func;</syntaxhighlight>


{{out}}
{{out}}
Line 2,829: Line 3,267:


=={{header|Sidef}}==
=={{header|Sidef}}==
<lang ruby>func map_range(a, b, x) {
<syntaxhighlight lang="ruby">func map_range(a, b, x) {
var (a1, a2, b1, b2) = (a.bounds, b.bounds);
var (a1, a2, b1, b2) = (a.bounds, b.bounds);
x-a1 * b2-b1 / a2-a1 + b1;
x-a1 * b2-b1 / a2-a1 + b1;
Line 2,839: Line 3,277:
for x in a {
for x in a {
say "#{x} maps to #{map_range(a, b, x)}";
say "#{x} maps to #{map_range(a, b, x)}";
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>0 maps to -1
<pre>0 maps to -1
Line 2,853: Line 3,291:
10 maps to 0</pre>
10 maps to 0</pre>


=={{header|SparForte}}==
As a structured script.
<syntaxhighlight lang="ada">#!/usr/local/bin/spar
pragma annotate( summary, "mapping" )
@( description, "The task is to write a function/subroutine/... that takes" )
@( description, "two ranges and a real number, and returns the mapping of" )
@( description, "the real number from the first to the second range. Use" )
@( description, "this function to map values from the range [0, 10] to the" )
@( description, "range [-1, 0]." )
@( see_also, "http://rosettacode.org/wiki/Map_range" )
@( author, "Ken O. Burtch" );
pragma license( unrestricted );

pragma restriction( no_external_commands );

procedure mapping is
type first_range is new float;
type second_range is new float;
-- Spar doesn't implement ranges so we'll use constants
first_range_first : constant first_range := 0.0;
first_range_last : constant first_range := 10.0;
second_range_first : constant second_range := -1.0;
second_range_last : constant second_range := 0.0;

function translate (first_range_value : first_range) return second_range is
b1 : constant float := float( second_range_first );
b2 : constant float := float( second_range_last );
a1 : constant float := float( first_range_first );
a2 : constant float := float( first_range_last );
result : float;
begin
result := b1 + (float (first_range_value) - a1) * (b2 - b1) / (a2 - a1);
return second_range(result);
end translate;

function translate_back (second_range_value : second_range) return first_range is
b1 : constant float := float (first_range_first);
b2 : constant float := float (first_range_last);
a1 : constant float := float (second_range_first);
a2 : constant float := float (second_range_last);
result : float;
begin
result := b1 + (float (second_range_value) - a1) * (b2 - b1) / (a2 - a1);
return first_range (result);
end translate_back;

test_value : first_range := first_range_first;
translated_value : second_range;
translated_back_value : first_range;
begin
loop
translated_value := translate( test_value );
translated_back_value := translate_back( translated_value );

? strings.image(test_value) & " maps to: "
& strings.image (translated_value);
? strings.image(translated_value) & " maps back to: "
& strings.image (translated_back_value);
exit when test_value = first_range_last;
test_value := @ + 1.0;
end loop;
end mapping;</syntaxhighlight>
{{out}}
<pre>
$ spar mapping.sp
0.0 maps to: -1.00000000000000E+00
-1.00000000000000E+00 maps back to: 0.00000000000000E+00
1.00000000000000E+00 maps to: -9.00000000000000E-01
-9.00000000000000E-01 maps back to: 1.00000000000000E+00
2.00000000000000E+00 maps to: -8.00000000000000E-01
-8.00000000000000E-01 maps back to: 2.00000000000000E+00
3.00000000000000E+00 maps to: -7.00000000000000E-01
-7.00000000000000E-01 maps back to: 3.00000000000000E+00
4.00000000000000E+00 maps to: -6.00000000000000E-01
-6.00000000000000E-01 maps back to: 4.00000000000000E+00
5.00000000000000E+00 maps to: -5.00000000000000E-01
-5.00000000000000E-01 maps back to: 5.00000000000000E+00
6.00000000000000E+00 maps to: -4.00000000000000E-01
-4.00000000000000E-01 maps back to: 6.00000000000000E+00
7.00000000000000E+00 maps to: -3.00000000000000E-01
-3.00000000000000E-01 maps back to: 7.00000000000000E+00
8.00000000000000E+00 maps to: -2.00000000000000E-01
-2.00000000000000E-01 maps back to: 8.00000000000000E+00
9.00000000000000E+00 maps to: -1.00000000000000E-01
-1.00000000000000E-01 maps back to: 9.00000000000000E+00
1.00000000000000E+01 maps to: 0.00000000000000E+00
0.00000000000000E+00 maps back to: 1.00000000000000E+01</pre>
=={{header|Stata}}==
=={{header|Stata}}==
The following program will map a variable to a new variable. It accepts '''if''' and '''in''' conditions.
The following program will map a variable to a new variable. It accepts '''if''' and '''in''' conditions.


<lang stata>program define maprange
<syntaxhighlight lang="stata">program define maprange
version 15.1
version 15.1
syntax varname(numeric) [if] [in], ///
syntax varname(numeric) [if] [in], ///
Line 2,877: Line 3,402:
qui gen `generate'=(`varlist'-`a')*`h'+`c' `if' `in'
qui gen `generate'=(`varlist'-`a')*`h'+`c' `if' `in'
}
}
end</lang>
end</syntaxhighlight>


'''Example'''
'''Example'''


<lang stata>clear
<syntaxhighlight lang="stata">clear
set obs 11
set obs 11
gen x=_n-1
gen x=_n-1
maprange x if mod(x,2)==0, gen(y) from(0 10) to(-10 10)
maprange x if mod(x,2)==0, gen(y) from(0 10) to(-10 10)
maprange x if mod(x,2)!=0, gen(y) from(0 10) to(-100 100) replace
maprange x if mod(x,2)!=0, gen(y) from(0 10) to(-100 100) replace
list</lang>
list</syntaxhighlight>


'''Output'''
'''Output'''
Line 2,910: Line 3,435:
=={{header|Swift}}==
=={{header|Swift}}==


<lang Swift>import Foundation
<syntaxhighlight lang="swift">import Foundation


func mapRanges(_ r1: ClosedRange<Double>, _ r2: ClosedRange<Double>, to: Double) -> Double {
func mapRanges(_ r1: ClosedRange<Double>, _ r2: ClosedRange<Double>, to: Double) -> Double {
Line 2,921: Line 3,446:
for i in 0...10 {
for i in 0...10 {
print(String(format: "%2d maps to %5.2f", i, mapRanges(0...10, -1...0, to: Double(i))))
print(String(format: "%2d maps to %5.2f", i, mapRanges(0...10, -1...0, to: Double(i))))
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 2,938: Line 3,463:


=={{header|Tcl}}==
=={{header|Tcl}}==
<lang tcl>package require Tcl 8.5
<syntaxhighlight lang="tcl">package require Tcl 8.5
proc rangemap {rangeA rangeB value} {
proc rangemap {rangeA rangeB value} {
lassign $rangeA a1 a2
lassign $rangeA a1 a2
lassign $rangeB b1 b2
lassign $rangeB b1 b2
expr {$b1 + ($value - $a1)*double($b2 - $b1)/($a2 - $a1)}
expr {$b1 + ($value - $a1)*double($b2 - $b1)/($a2 - $a1)}
}</lang>
}</syntaxhighlight>
Demonstration (using a curried alias to bind the ranges mapped from and to):
Demonstration (using a curried alias to bind the ranges mapped from and to):
<lang tcl>interp alias {} demomap {} rangemap {0 10} {-1 0}
<syntaxhighlight lang="tcl">interp alias {} demomap {} rangemap {0 10} {-1 0}
for {set i 0} {$i <= 10} {incr i} {
for {set i 0} {$i <= 10} {incr i} {
puts [format "%2d -> %5.2f" $i [demomap $i]]
puts [format "%2d -> %5.2f" $i [demomap $i]]
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 2,966: Line 3,491:
=={{header|Ursala}}==
=={{header|Ursala}}==
The function <code>f</code> is defined using pattern matching and substitution, taking a pair of pairs of interval endpoints and a number as parameters, and returning a number.
The function <code>f</code> is defined using pattern matching and substitution, taking a pair of pairs of interval endpoints and a number as parameters, and returning a number.
<lang Ursala>#import flo
<syntaxhighlight lang="ursala">#import flo


f((("a1","a2"),("b1","b2")),"s") = plus("b1",div(minus("s","a1"),minus("a2","a1")))
f((("a1","a2"),("b1","b2")),"s") = plus("b1",div(minus("s","a1"),minus("a2","a1")))
Line 2,972: Line 3,497:
#cast %eL
#cast %eL


test = f* ((0.,10.),(-1.,0.))-* ari11/0. 10.</lang>
test = f* ((0.,10.),(-1.,0.))-* ari11/0. 10.</syntaxhighlight>
{{out}}
{{out}}
<pre><
<pre><
Line 2,987: Line 3,512:
0.000000e+00></pre>
0.000000e+00></pre>
A more idiomatic way is to define f as a second order function
A more idiomatic way is to define f as a second order function
<lang Ursala>f(("a1","a2"),("b1","b2")) "s" = ...</lang>
<syntaxhighlight lang="ursala">f(("a1","a2"),("b1","b2")) "s" = ...</syntaxhighlight>
with the same right hand side as above, so that it takes a pair of intervals and returns a function mapping numbers in one interval to numbers in the other.
with the same right hand side as above, so that it takes a pair of intervals and returns a function mapping numbers in one interval to numbers in the other.


Line 2,993: Line 3,518:


=={{header|Vala}}==
=={{header|Vala}}==
<lang vala>double map_range(double s, int a1, int a2, int b1, int b2) {
<syntaxhighlight lang="vala">double map_range(double s, int a1, int a2, int b1, int b2) {
return b1+(s-a1)*(b2-b1)/(a2-a1);
return b1+(s-a1)*(b2-b1)/(a2-a1);
}
}
Line 3,001: Line 3,526:
print("%2d maps to %5.2f\n", s, map_range(s, 0, 10, -1, 0));
print("%2d maps to %5.2f\n", s, map_range(s, 0, 10, -1, 0));
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 3,019: Line 3,544:


=={{header|WDTE}}==
=={{header|WDTE}}==
<lang WDTE>let mapRange r1 r2 s =>
<syntaxhighlight lang="wdte">let mapRange r1 r2 s =>
+
+
(at r2 0)
(at r2 0)
Line 3,047: Line 3,572:
-> s.map (@ print v => str.format '{} -> {}' (at v 0) (at v 1) -- io.writeln io.stdout)
-> s.map (@ print v => str.format '{} -> {}' (at v 0) (at v 1) -- io.writeln io.stdout)
-> s.drain
-> s.drain
;</lang>
;</syntaxhighlight>


{{out}}
{{out}}
Line 3,063: Line 3,588:
=={{header|Wren}}==
=={{header|Wren}}==
{{libheader|Wren-fmt}}
{{libheader|Wren-fmt}}
<lang ecmascript>import "/fmt" for Fmt
<syntaxhighlight lang="wren">import "./fmt" for Fmt


var mapRange = Fn.new { |a, b, s| b.from + (s - a.from) * (b.to - b.from) / (a.to - a.from) }
var mapRange = Fn.new { |a, b, s| b.from + (s - a.from) * (b.to - b.from) / (a.to - a.from) }
Line 3,071: Line 3,596:
for (s in a) {
for (s in a) {
var t = mapRange.call(a, b, s)
var t = mapRange.call(a, b, s)
var f = (t >= 0) ? " " : ""
Fmt.print("$2d maps to $ h", s, t)
}</syntaxhighlight>
System.print("%(Fmt.d(2, s)) maps to %(f)%(t)")
}</lang>


{{out}}
{{out}}
Line 3,091: Line 3,615:


=={{header|XPL0}}==
=={{header|XPL0}}==
<lang XPL0>include c:\cxpl\codes;
<syntaxhighlight lang="xpl0">include c:\cxpl\codes;


func real Map(A1, A2, B1, B2, S);
func real Map(A1, A2, B1, B2, S);
Line 3,103: Line 3,627:
CrLf(0);
CrLf(0);
];
];
]</lang>
]</syntaxhighlight>


{{out}}
{{out}}
Line 3,121: Line 3,645:


=={{header|Yabasic}}==
=={{header|Yabasic}}==
<lang Yabasic>sub MapRange(s, a1, a2, b1, b2)
<syntaxhighlight lang="yabasic">sub MapRange(s, a1, a2, b1, b2)
return b1+(s-a1)*(b2-b1)/(a2-a1)
return b1+(s-a1)*(b2-b1)/(a2-a1)
end sub
end sub
Line 3,127: Line 3,651:
for i = 0 to 10 step 2
for i = 0 to 10 step 2
print i, " : ", MapRange(i,0,10,-1,0)
print i, " : ", MapRange(i,0,10,-1,0)
next</lang>
next</syntaxhighlight>


=={{header|zkl}}==
=={{header|zkl}}==
<lang zkl>fcn mapRange([(a1,a2)], [(b1,b2)], s) // a1a2 is List(a1,a2)
<syntaxhighlight lang="zkl">fcn mapRange([(a1,a2)], [(b1,b2)], s) // a1a2 is List(a1,a2)
{ b1 + ((s - a1) * (b2 - b1) / (a2 - a1)) }
{ b1 + ((s - a1) * (b2 - b1) / (a2 - a1)) }


Line 3,136: Line 3,660:
foreach s in ([0.0 .. 10]){
foreach s in ([0.0 .. 10]){
"%2d maps to %5.2f".fmt(s,mapRange(r1,r2, s)).println();
"%2d maps to %5.2f".fmt(s,mapRange(r1,r2, s)).println();
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>

Revision as of 18:45, 17 February 2024

Task
Map range
You are encouraged to solve this task according to the task description, using any language you may know.

Given two ranges:

  •     and
  •   ;
  •   then a value     in range  
  •   is linearly mapped to a value     in range  

  where:

  •  


Task

Write a function/subroutine/... that takes two ranges and a real number, and returns the mapping of the real number from the first to the second range.

Use this function to map values from the range   [0, 10]   to the range   [-1, 0].


Extra credit

Show additional idiomatic ways of performing the mapping, using tools available to the language.

11l

Translation of: Python
F maprange(a, b, s)
   R b[0] + (Float(s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]))

L(s) 0..10
   print(‘#2 maps to #.’.format(s, maprange((0, 10), (-1, 0), s)))
Output:
 0 maps to -1
 1 maps to -0.9
 2 maps to -0.8
 3 maps to -0.7
 4 maps to -0.6
 5 maps to -0.5
 6 maps to -0.4
 7 maps to -0.3
 8 maps to -0.2
 9 maps to -0.1
10 maps to 0

6502 Assembly

A range like [0, n] for some natural number n < 255 can be easily mapped with a lookup table. The second range can be anything, as long as each entry is the same length and are stored consecutively in the desired order. This method requires a bit of compile-time knowledge, but is very efficient in terms of speed. Each element Bn is stored at relative offset An .

mapping:
byte $00,$00,$80,$BF ;-1.0f (stored little-endian so the bytes are backwards)
byte $66,$66,$66,$BF ;-0.9f
byte $CD,$CC,$4C,$BF ;-0.8f
byte $33,$33,$33,$BF ;-0.7f
etc.

If the range isn't [0, n], but begins at some other natural number [k, n] where k,n < 255 , we can express it as [0, n-k] instead and simply subtract the "key" at runtime to get the offset.

This method is very convenient for implementing ASCII into hardware that lacks a built-in system font (like the NES). You can save graphics memory by mapping tile number 0 to ASCII 32, tile number 01 to 33, and so on. Had you mapped them "correctly," (i.e. tile number 32 to ASCII 32) you would still need a "blank tile" as tile number zero. So the easier solution is to subtract 32 from the character code before printing.

;runs during non-maskable interrupt.
PrintChar:  
;a = char to print
SEC
SBC #$32 ;subtract ascii offset to map the index to the correct tile graphics data.

;everything below this comment is hardware-specific mumbo-jumbo, feel free to ignore it if you don't care.
;ideally you'd want to do this before getting here so that the only thing that happens during NMI is the write to vram.
pha  
LDA Cursor_Y
ASL
ASL
ASL
ASL
ASL
STA tempY  ;row * 32
LDA #$20
ADC Cursor_X
STA tempX
LDA $2002 ;reset picture processor high-low latch
LDA tempX
STA $2006 ;this register is big-endian for some reason. Which is why I had to store Cursor_Y << 5 into tempY rather than here directly.
LDA tempY
STA $2006
PLA
STA $2007

ACL2

(defun mapping (a1 a2 b1 b2 s)
   (+ b1 (/ (* (- s a1)
               (- b2 b1))
            (- a2 a1))))

(defun map-each (a1 a2 b1 b2 ss)
   (if (endp ss)
       nil
       (cons (mapping a1 a2 b1 b2 (first ss))
             (map-each a1 a2 b1 b2 (rest ss)))))

(map-each 0 10 -1 0 '(0 1 2 3 4 5 6 7 8 9 10))

;; (-1 -9/10 -4/5 -7/10 -3/5 -1/2 -2/5 -3/10 -1/5 -1/10 0)

Action!

INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit

PROC Map(REAL POINTER a1,a2,b1,b2,s,res)
  REAL tmp1,tmp2,tmp3

  RealSub(s,a1,tmp1) ;tmp1=s-a1
  RealSub(b2,b1,tmp2) ;tmp2=b2-b1
  RealMult(tmp1,tmp2,tmp3) ;tmp3=(s-a1)*(b2-b1)
  RealSub(a2,a1,tmp1) ;tmp1=a2-a1
  RealDiv(tmp3,tmp1,tmp2) ;tmp2=(s-a1)*(b2-b1)/(a2-a1)
  RealAdd(b1,tmp2,res) ;res=b1+(s-a1)*(b2-b1)/(a2-a1)
RETURN

PROC Main()
  BYTE i
  REAL a1,a2,b1,b2,s,res

  Put(125) PutE() ;clear screen

  ValR("0",a1) ValR("10",a2)
  ValR("-1",b1) ValR("0",b2)

  FOR i=0 TO 10
  DO
    IntToReal(i,s)
    Map(a1,a2,b1,b2,s,res)
    PrintR(s) Print(" maps to ")
    PrintRE(res)
  OD
RETURN
Output:

Screenshot from Atari 8-bit computer

0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

Ada

with Ada.Text_IO;
procedure Map is
   type First_Range  is new Float range 0.0 .. 10.0;
   type Second_Range is new Float range -1.0 .. 0.0;
   function Translate (Value : First_Range) return Second_Range is
      B1 : Float := Float (Second_Range'First);
      B2 : Float := Float (Second_Range'Last);
      A1 : Float := Float (First_Range'First);
      A2 : Float := Float (First_Range'Last);
      Result : Float;
   begin
      Result := B1 + (Float (Value) - A1) * (B2 - B1) / (A2 - A1);
      return Second_Range (Result);
   end;
   function Translate (Value : Second_Range) return First_Range is
      B1 : Float := Float (First_Range'First);
      B2 : Float := Float (First_Range'Last);
      A1 : Float := Float (Second_Range'First);
      A2 : Float := Float (Second_Range'Last);
      Result : Float;
   begin
      Result := B1 + (Float (Value) - A1) * (B2 - B1) / (A2 - A1);
      return First_Range (Result);
   end;
   Test_Value : First_Range := First_Range'First;
begin
   loop
      Ada.Text_IO.Put_Line (First_Range'Image (Test_Value) & " maps to: "
                          & Second_Range'Image (Translate (Test_Value)));
      exit when Test_Value = First_Range'Last;
      Test_Value := Test_Value + 1.0;
   end loop;
end Map;
Output:
 0.00000E+00 maps to: -1.00000E+00
 1.00000E+00 maps to: -9.00000E-01
 2.00000E+00 maps to: -8.00000E-01
 3.00000E+00 maps to: -7.00000E-01
 4.00000E+00 maps to: -6.00000E-01
 5.00000E+00 maps to: -5.00000E-01
 6.00000E+00 maps to: -4.00000E-01
 7.00000E+00 maps to: -3.00000E-01
 8.00000E+00 maps to: -2.00000E-01
 9.00000E+00 maps to: -1.00000E-01
 1.00000E+01 maps to:  0.00000E+00

ALGOL 68

# maps a real s in the range [ a1, a2 ] to the range [ b1, b2 ]           #
# there are no checks that s is in the range or that the ranges are valid #
PROC map range = ( REAL s, a1, a2, b1, b2 )REAL:
    b1 + ( ( s - a1 ) * ( b2 - b1 ) ) / ( a2 - a1 );

# test the mapping #
FOR i FROM 0 TO 10 DO
    print( ( whole( i, -2 ), " maps to ", fixed( map range( i, 0, 10, -1, 0 ), -8, 2 ), newline ) )
OD
Output:
 0 maps to    -1.00
 1 maps to    -0.90
 2 maps to    -0.80
 3 maps to    -0.70
 4 maps to    -0.60
 5 maps to    -0.50
 6 maps to    -0.40
 7 maps to    -0.30
 8 maps to    -0.20
 9 maps to    -0.10
10 maps to     0.00

Amazing Hopper

La función "Seqspaced" es una macro-sustitución de "seqsp", y está construida, internamente, como una rutina en C que realiza el siguiente cálculo (en pseudocódigo):

double inc = (nHasta - nDesde) / ( nTotal - 1);
lista[0] = nDesde;
lista[nTotal] = nHasta;
for( n=1; n<nTotal; n++){
    lista[n] = lista[n-1] + inc;
}

Macro-sustitución de "Seqspaced":

#defn  Seqspaced(__X__,__Y__,__Z__,_V_)   #ATOM#CMPLX;#ATOM#CMPLX;#ATOM#CMPLX;keep;lthan(1);\
                                          do{{"Seqspaced: num elements < 1"}throw(2301)},seqsp(_V_)

Otras macrosustituciones:

#defn  Toksep(__X__)       #ATOM#CMPLX;toksep;
#defn  Cat(_X_,*)          #ATOM#CMPLX;#GENCODE $$$*$$$ #ATCMLIST;cat; #ENDGEN
#defn  Justleft(_X_,_V_)   {" "};#ATOM#CMPLX;#ATOM#CMPLX;padright;

Código que resuelve la tarea:

#include <jambo.h>
Main
   v=0,w=0
   Seqspaced(-1,0,11,w)  // [-1,0}->[0-10]=11 números
   Seqspaced(0,10,11,v)
   Toksep( "\n" )
   Cat( Justright(5,Str(v))," => ",Justright(5,Str(w))), Prnl
End
Output:
$ hopper maprange.jambo 
    0 =>    -1
    1 =>  -0.9
    2 =>  -0.8
    3 =>  -0.7
    4 =>  -0.6
    5 =>  -0.5
    6 =>  -0.4
    7 =>  -0.3
    8 =>  -0.2
    9 =>  -0.1
   10 =>     0
$

AppleScript

------------------------ MAP RANGE -----------------------

-- rangeMap :: (Num, Num) -> (Num, Num) -> Num -> Num
on rangeMap(a, b)
    script
        on |λ|(s)
            set {a1, a2} to a
            set {b1, b2} to b
            b1 + ((s - a1) * (b2 - b1)) / (a2 - a1)
        end |λ|
    end script
end rangeMap


--------------------------- TEST -------------------------
on run
    set mapping to rangeMap({0, 10}, {-1, 0})
    
    set xs to enumFromTo(0, 10)
    set ys to map(mapping, xs)
    set zs to map(approxRatio(0), ys)
    
    unlines(zipWith3(formatted, xs, ys, zs))
end run


------------------------- DISPLAY ------------------------

-- formatted :: Int -> Float -> Ratio -> String
on formatted(x, m, r)
    set fract to showRatio(r)
    set {n, d} to splitOn("/", fract)
    
    (justifyRight(2, space, x as string) & "   ->   " & ¬
        justifyRight(4, space, m as string)) & "   =   " & ¬
        justifyRight(2, space, n) & "/" & d
end formatted


-------------------- GENERIC FUNCTIONS -------------------

-- Absolute value.
-- abs :: Num -> Num
on abs(x)
    if 0 > x then
        -x
    else
        x
    end if
end abs


-- approxRatio :: Real -> Real -> Ratio
on approxRatio(epsilon)
    script
        on |λ|(n)
            if {real, integer} contains (class of epsilon) and 0 < epsilon then
                set e to epsilon
            else
                set e to 1 / 10000
            end if
            
            script gcde
                on |λ|(e, x, y)
                    script _gcd
                        on |λ|(a, b)
                            if b < e then
                                a
                            else
                                |λ|(b, a mod b)
                            end if
                        end |λ|
                    end script
                    |λ|(abs(x), abs(y)) of _gcd
                end |λ|
            end script
            
            set c to |λ|(e, 1, n) of gcde
            ratio((n div c), (1 div c))
        end |λ|
    end script
end approxRatio


-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
    if m  n then
        set lst to {}
        repeat with i from m to n
            set end of lst to i
        end repeat
        return lst
    else
        return {}
    end if
end enumFromTo


-- gcd :: Int -> Int -> Int
on gcd(a, b)
    set x to abs(a)
    set y to abs(b)
    repeat until y = 0
        if x > y then
            set x to x - y
        else
            set y to y - x
        end if
    end repeat
    return x
end gcd


-- justifyLeft :: Int -> Char -> String -> String
on justifyLeft(n, cFiller, strText)
    if n > length of strText then
        text 1 thru n of (strText & replicate(n, cFiller))
    else
        strText
    end if
end justifyLeft


-- justifyRight :: Int -> Char -> String -> String
on justifyRight(n, cFiller, strText)
    if n > length of strText then
        text -n thru -1 of ((replicate(n, cFiller) as text) & strText)
    else
        strText
    end if
end justifyRight


-- length :: [a] -> Int
on |length|(xs)
    set c to class of xs
    if list is c or string is c then
        length of xs
    else
        (2 ^ 29 - 1) -- (maxInt - simple proxy for non-finite)
    end if
end |length|


-- Lift 2nd class handler function into 1st class script wrapper 
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn


-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map


-- minimum :: Ord a => [a] -> a
on minimum(xs)
    set lng to length of xs
    if lng < 1 then return missing value
    set m to item 1 of xs
    repeat with x in xs
        set v to contents of x
        if v < m then set m to v
    end repeat
    return m
end minimum


-- ratio :: Int -> Int -> Ratio Int
on ratio(x, y)
    script go
        on |λ|(x, y)
            if 0  y then
                if 0  x then
                    set d to gcd(x, y)
                    {type:"Ratio", n:(x div d), d:(y div d)}
                else
                    {type:"Ratio", n:0, d:1}
                end if
            else
                missing value
            end if
        end |λ|
    end script
    go's |λ|(x * (signum(y)), abs(y))
end ratio


-- Egyptian multiplication - progressively doubling a list, appending
-- stages of doubling to an accumulator where needed for binary 
-- assembly of a target length
-- replicate :: Int -> a -> [a]
on replicate(n, a)
    set out to {}
    if n < 1 then return out
    set dbl to {a}
    
    repeat while (n > 1)
        if (n mod 2) > 0 then set out to out & dbl
        set n to (n div 2)
        set dbl to (dbl & dbl)
    end repeat
    return out & dbl
end replicate


-- showRatio :: Ratio -> String
on showRatio(r)
    (n of r as string) & "/" & (d of r as string)
end showRatio


-- signum :: Num -> Num
on signum(x)
    if x < 0 then
        -1
    else if x = 0 then
        0
    else
        1
    end if
end signum


-- splitOn :: String -> String -> [String]
on splitOn(pat, src)
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, pat}
    set xs to text items of src
    set my text item delimiters to dlm
    return xs
end splitOn


-- take :: Int -> [a] -> [a]
-- take :: Int -> String -> String
on take(n, xs)
    set c to class of xs
    if list is c then
        if 0 < n then
            items 1 thru min(n, length of xs) of xs
        else
            {}
        end if
    else if string is c then
        if 0 < n then
            text 1 thru min(n, length of xs) of xs
        else
            ""
        end if
    else if script is c then
        set ys to {}
        repeat with i from 1 to n
            set v to xs's |λ|()
            if missing value is v then
                return ys
            else
                set end of ys to v
            end if
        end repeat
        return ys
    else
        missing value
    end if
end take


-- unlines :: [String] -> String
on unlines(xs)
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, linefeed}
    set str to xs as text
    set my text item delimiters to dlm
    str
end unlines


-- zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
on zipWith3(f, xs, ys, zs)
    set lng to minimum({length of xs, length of ys, length of zs})
    if 1 > lng then return {}
    set lst to {}
    tell mReturn(f)
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, item i of ys, item i of zs)
        end repeat
        return lst
    end tell
end zipWith3
Output:
 0   ->   -1.0   =   -1/1
 1   ->   -0.9   =   -9/10
 2   ->   -0.8   =   -4/5
 3   ->   -0.7   =   -7/10
 4   ->   -0.6   =   -3/5
 5   ->   -0.5   =   -1/2
 6   ->   -0.4   =   -2/5
 7   ->   -0.3   =   -3/10
 8   ->   -0.2   =   -1/5
 9   ->   -0.1   =   -1/10
10   ->    0.0   =    0/1

Arturo

getMapped: function [a,b,i][
    round .to:1 b\0 + ((i - a\0) * (b\1 - b\0))/(a\1 - a\0)
]

rangeA: @[0.0 10.0]
rangeB: @[0-1.0 0.0]

loop 0..10 'x [
    mapped: getMapped rangeA rangeB to :floating x
    print [x "maps to" mapped]
]
Output:
0 maps to -1.0 
1 maps to -0.9 
2 maps to -0.8 
3 maps to -0.7 
4 maps to -0.6 
5 maps to -0.5 
6 maps to -0.4 
7 maps to -0.3 
8 maps to -0.2 
9 maps to -0.1 
10 maps to 0.0

AutoHotkey

Translation of: C
 
mapRange(a1, a2, b1, b2, s)
{
	return b1 + (s-a1)*(b2-b1)/(a2-a1)
}

out := "Mapping [0,10] to [-1,0] at intervals of 1:`n"

Loop 11
	out .= "f(" A_Index-1 ") = " mapRange(0,10,-1,0,A_Index-1) "`n"
MsgBox % out

AWK

# syntax: GAWK -f MAP_RANGE.AWK
BEGIN {
    a1 = 0
    a2 = 10
    b1 = -1
    b2 = 0
    for (i=a1; i<=a2; i++) {
      printf("%g maps to %g\n",i,map_range(a1,a2,b1,b2,i))
    }
    exit(0)
}
function map_range(a1,a2,b1,b2,num) {
    return b1 + ((num-a1) * (b2-b1) / (a2-a1))
}
Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

Axiom

Axiom provides a Segment domain for intervals. The following uses a closure for a mapRange function over fields, which provides for some generality.

)abbrev package TESTP TestPackage
TestPackage(R:Field) : with
    mapRange: (Segment(R), Segment(R)) -> (R->R) 
  == add
    mapRange(fromRange, toRange) == 
      (a1,a2,b1,b2) := (lo fromRange,hi fromRange,lo toRange,hi toRange)
      (x:R):R +-> b1+(x-a1)*(b2-b1)/(a2-a1)

Use:

f := mapRange(1..10,a..b)  
[(xi,f xi) for xi in 1..10]
Output:
              b + 8a      2b + 7a      b + 2a      4b + 5a      5b + 4a
   [(1,a), (2,------), (3,-------), (4,------), (5,-------), (6,-------),
                 9           9            3           9            9
       2b + a      7b + 2a      8b + a
    (7,------), (8,-------), (9,------), (10,b)]
          3           9            9
                             Type: List(Tuple(Fraction(Polynomial(Integer))))

BASIC

BASIC256

Translation of: FreeBASIC
function MapRange(s, a1, a2, b1, b2)
	return b1+(s-a1)*(b2-b1)/(a2-a1)
end function

for i = 0 to 10
	print i; " maps to "; MapRange(i,0,10,-1,0)
next i
end
Output:
Igual que la entrada de FreeBASIC.

BBC BASIC

      @% = 5 : REM Column width
      DIM range{l, h}
      DIM A{} = range{}, B{} = range{}
      A.l = 0 : A.h = 10
      B.l = -1 : B.h = 0
      FOR n = 0 TO 10
        PRINT n " maps to " FNmaprange(A{}, B{}, n)
      NEXT
      END
      
      DEF FNmaprange(a{}, b{}, s)
      = b.l + (s - a.l) * (b.h - b.l) / (a.h - a.l)
Output:
    0 maps to    -1
    1 maps to  -0.9
    2 maps to  -0.8
    3 maps to  -0.7
    4 maps to  -0.6
    5 maps to  -0.5
    6 maps to  -0.4
    7 maps to  -0.3
    8 maps to  -0.2
    9 maps to  -0.1
   10 maps to     0

Commodore BASIC

10 REM MAP RANGE
20 REM COMMODORE BASIC 2.0
30 REM ================================
40 A1 = 0 : A2 = 10
50 B1 = -1 : B2 = 0
60 DEF FN MR(S)=B1+(S-A1)*(B2-B1)/(A2-A1)
70 FOR S=0 TO 10
80   PRINT S;"MAPS TO ";FN MR(S)
90 NEXT
Output:
 0 MAPS TO -1
 1 MAPS TO -.9
 2 MAPS TO -.8
 3 MAPS TO -.7
 4 MAPS TO -.6
 5 MAPS TO -.5
 6 MAPS TO -.4
 7 MAPS TO -.3
 8 MAPS TO -.2
 9 MAPS TO -.1
 10 MAPS TO  0

IS-BASIC

100 PROGRAM "MapRange.bas"
110 LET A1=0:LET A2=10
120 LET B1=-1:LET B2=0
130 DEF MR(S)=B1+(S-A1)*(B2-B1)/(A2-A1)
140 FOR I=0 TO 10
150   PRINT I;"maps to ";MR(I)
160 NEXT

bc

/* map s from [a, b] to [c, d] */
define m(a, b, c, d, s) {
	return (c + (s - a) * (d - c) / (b - a))
}

scale = 6  /* division to 6 decimal places */
"[0, 10] => [-1, 0]
"
for (i = 0; i <= 10; i += 2) {
	/*
         * If your bc(1) has a print statement, you can try
	 * print i, " => ", m(0, 10, -1, 0, i), "\n"
	 */
	i; "   => "; m(0, 10, -1, 0, i)
}
quit
Output:
[0, 10] => [-1, 0]
0
   => -1.000000
2
   => -.800000
4
   => -.600000
6
   => -.400000
8
   => -.200000
10
   => 0.000000

BQN

A direct implementation of the specification.

_map_ is a 2-modifier which returns a mapping function given two ranges.

_map_  {
 a1a2 _𝕣_ b1b2 s:
 b1 + ((s - a1) × b2 - b1) ÷ a2 - a1
}

ZeroTen  010 _map_ ¯10

•Show ZeroTen 0.1
•Show ZeroTen 8
¯0.99
¯0.19999999999999996

Try It!

Bracmat

Translation of: C
( ( mapRange
  =   a1,a2,b1,b2,s
    .   !arg:(?a1,?a2.?b1,?b2.?s)
      & !b1+(!s+-1*!a1)*(!b2+-1*!b1)*(!a2+-1*!a1)^-1
  )
& out$"Mapping [0,10] to [-1,0] at intervals of 1:"
& 0:?n
&   whl
  ' ( !n:~>10
    & out$("f(" !n ") = " flt$(mapRange$(0,10.-1,0.!n),2))
    & 1+!n:?n
    )
);
Output:
Mapping [0,10] to [-1,0] at intervals of 1:
f( 0 ) =  -1,00*10E0
f( 1 ) =  -9,00*10E-1
f( 2 ) =  -8,00*10E-1
f( 3 ) =  -7,00*10E-1
f( 4 ) =  -6,00*10E-1
f( 5 ) =  -5,00*10E-1
f( 6 ) =  -4,00*10E-1
f( 7 ) =  -3,00*10E-1
f( 8 ) =  -2,00*10E-1
f( 9 ) =  -1,00*10E-1
f( 10 ) =  0

C

#include <stdio.h>

#define mapRange(a1,a2,b1,b2,s) (b1 + (s-a1)*(b2-b1)/(a2-a1))

int main()
{
	int i;
	puts("Mapping [0,10] to [-1,0] at intervals of 1:");
	
	for(i=0;i<=10;i++)
	{
		printf("f(%d) = %g\n",i,mapRange(0,10,-1,0,i));
	}
	
	return 0;
}
Output:
Mapping [0,10] to [-1,0] at intervals of 1:
f(0) = -1
f(1) = -0.9
f(2) = -0.8
f(3) = -0.7
f(4) = -0.6
f(5) = -0.5
f(6) = -0.4
f(7) = -0.3
f(8) = -0.2
f(9) = -0.1
f(10) = 0

C#

using System;
using System.Linq;

public class MapRange
{
    public static void Main() {
        foreach (int i in Enumerable.Range(0, 11))
            Console.WriteLine($"{i} maps to {Map(0, 10, -1, 0, i)}");
    }
    
    static double Map(double a1, double a2, double b1, double b2, double s) => b1 + (s - a1) * (b2 - b1) / (a2 - a1);
}
Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

C++

This example defines a template function to handle the mapping, using two std::pair objects to define the source and destination ranges. It returns the provided value mapped into the target range.

It's not written efficiently; certainly, there can be fewer explicit temporary variables. The use of the template offers a choice in types for precision and accuracy considerations, though one area for improvement might be to allow a different type for intermediate calculations.

#include <iostream>
#include <utility>

template<typename tVal>
tVal map_value(std::pair<tVal,tVal> a, std::pair<tVal, tVal> b, tVal inVal)
{
  tVal inValNorm = inVal - a.first;
  tVal aUpperNorm = a.second - a.first;
  tVal normPosition = inValNorm / aUpperNorm;

  tVal bUpperNorm = b.second - b.first;
  tVal bValNorm = normPosition * bUpperNorm;
  tVal outVal = b.first + bValNorm;

  return outVal;
}

int main()
{
  std::pair<float,float> a(0,10), b(-1,0);

  for(float value = 0.0; 10.0 >= value; ++value)
    std::cout << "map_value(" << value << ") = " << map_value(a, b, value) << std::endl;

  return 0;
}
Output:
map_value(0) = -1
map_value(1) = -0.9
map_value(2) = -0.8
map_value(3) = -0.7
map_value(4) = -0.6
map_value(5) = -0.5
map_value(6) = -0.4
map_value(7) = -0.3
map_value(8) = -0.2
map_value(9) = -0.1
map_value(10) = 0

Clojure

Translation of: Python
(defn maprange [[a1 a2] [b1 b2] s]
	(+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))
 
> (doseq [s (range 11)]
       (printf "%2s maps to %s\n" s (maprange [0 10] [-1 0] s)))

 0 maps to -1
 1 maps to -9/10
 2 maps to -4/5
 3 maps to -7/10
 4 maps to -3/5
 5 maps to -1/2
 6 maps to -2/5
 7 maps to -3/10
 8 maps to -1/5
 9 maps to -1/10
10 maps to 0

COBOL

Works with: OpenCOBOL
       IDENTIFICATION DIVISION.
       PROGRAM-ID. demo-map-range.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  i                       USAGE FLOAT-LONG.

       01  mapped-num              USAGE FLOAT-LONG.

       01  a-begin                 USAGE FLOAT-LONG VALUE 0.
       01  a-end                   USAGE FLOAT-LONG VALUE 10.

       01  b-begin                 USAGE FLOAT-LONG VALUE -1.
       01  b-end                   USAGE FLOAT-LONG VALUE 0.

       01  i-display               PIC --9.9.
       01  mapped-display          PIC --9.9.

       PROCEDURE DIVISION.
           PERFORM VARYING i FROM 0 BY 1 UNTIL i > 10
               CALL "map-range" USING CONTENT a-begin, a-end, b-begin,
                   b-end, i, REFERENCE mapped-num
               COMPUTE i-display ROUNDED = i
               COMPUTE mapped-display ROUNDED = mapped-num
               DISPLAY FUNCTION TRIM(i-display) " maps to "
                   FUNCTION TRIM(mapped-display)
           END-PERFORM
           .
       END PROGRAM demo-map-range.


       IDENTIFICATION DIVISION.
       PROGRAM-ID. map-range.

       DATA DIVISION.
       LINKAGE SECTION.
       01  a-begin                 USAGE FLOAT-LONG.
       01  a-end                   USAGE FLOAT-LONG.

       01  b-begin                 USAGE FLOAT-LONG.
       01  b-end                   USAGE FLOAT-LONG.

       01  val-to-map              USAGE FLOAT-LONG.

       01  ret                     USAGE FLOAT-LONG.

       PROCEDURE DIVISION USING a-begin, a-end, b-begin, b-end,
               val-to-map, ret.
           COMPUTE ret = 
               b-begin + ((val-to-map - a-begin) * (b-end - b-begin)
                   / (a-end - a-begin))
           .
       END PROGRAM map-range.

The output is identical to the output of the Common Lisp example.

CoffeeScript

mapRange = (a1,a2,b1,b2,s) ->
    t = b1 + ((s-a1)*(b2 - b1)/(a2-a1))

for s in [0..10]
    console.log("#{s} maps to #{mapRange(0,10,-1,0,s)}")
Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.30000000000000004
8 maps to -0.19999999999999996
9 maps to -0.09999999999999998
10 maps to 0

Common Lisp

(defun map-range (a1 a2 b1 b2 s)
  (+ b1
     (/ (* (- s a1)
	   (- b2 b1))
	(- a2 a1))))

(loop
   for i from 0 to 10
   do (format t "~F maps to ~F~C" i
	      (map-range 0 10 -1 0 i)
	      #\Newline))
Output:
0.0 maps to -1.0
1.0 maps to -0.9
2.0 maps to -0.8
3.0 maps to -0.7
4.0 maps to -0.6
5.0 maps to -0.5
6.0 maps to -0.4
7.0 maps to -0.3
8.0 maps to -0.2
9.0 maps to -0.1
10.0 maps to 0.0

Craft Basic

define a1 = 0, b1 = 0, a2 = 0, b2 = 0

for i = 0 to 10

	let s = i
	let a1 = 0
	let a2 = 10
	let b1 = -1
	let b2 = 0

	print i, " : ", b1 + ( s - a1 ) * ( b2 - b1 ) / ( a2 - a1 )

next i
Output:
0 : -1

1 : -0.9000 2 : -0.8000 3 : -0.7000 4 : -0.6000 5 : -0.5000 6 : -0.4000 7 : -0.3000 8 : -0.2000 9 : -0.1000

10 : 0

D

double mapRange(in double[] a, in double[] b, in double s)
pure nothrow @nogc {
    return b[0] + ((s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]));
}

void main() {
    import std.stdio;

    immutable r1 = [0.0, 10.0];
    immutable r2 = [-1.0, 0.0];
    foreach (immutable s; 0 .. 11)
        writefln("%2d maps to %5.2f", s, mapRange(r1, r2, s));
}
Output:
 0 maps to -1.00
 1 maps to -0.90
 2 maps to -0.80
 3 maps to -0.70
 4 maps to -0.60
 5 maps to -0.50
 6 maps to -0.40
 7 maps to -0.30
 8 maps to -0.20
 9 maps to -0.10
10 maps to  0.00

Delphi

See #Pascal.

EchoLisp

EchoLisp provides several native interpolation functions: smoothstep, s-curve, .. and linear which performs linear interpolation.

(lib 'plot) ;; interpolation functions
(lib 'compile)

;; rational version
(define (q-map-range x xmin xmax ymin ymax) (+ ymin (/ ( * (- x xmin) (- ymax ymin)) (- xmax xmin))))

;; float version
(define (map-range x xmin xmax ymin ymax) (+ ymin (// ( * (- x xmin) (- ymax ymin)) (- xmax xmin))))
; accelerate it
(compile 'map-range "-vf")

(q-map-range 4 0 10 -1 0)
     -3/5
(map-range 4 0 10 -1 0)
     -0.6
(linear 4 0 10 -1 0) ;; native
     -0.6

(for [(x (in-range 0 10))] (writeln x (q-map-range x 0 10 -1 0) (map-range x 0 10 -1 0)))

0     -1     -1    
1     -9/10     -0.9    
2     -4/5     -0.8    
3     -7/10     -0.7    
4     -3/5     -0.6    
5     -1/2     -0.5    
6     -2/5     -0.4    
7     -3/10     -0.3    
8     -1/5     -0.2    
9     -1/10     -0.1

Elixir

defmodule RC do
  def map_range(a1 .. a2, b1 .. b2, s) do
    b1 + (s - a1) * (b2 - b1) / (a2 - a1)
  end
end

Enum.each(0..10, fn s ->
  :io.format "~2w map to ~7.3f~n", [s, RC.map_range(0..10, -1..0, s)]
end)
Output:
 0 map to  -1.000
 1 map to  -0.900
 2 map to  -0.800
 3 map to  -0.700
 4 map to  -0.600
 5 map to  -0.500
 6 map to  -0.400
 7 map to  -0.300
 8 map to  -0.200
 9 map to  -0.100
10 map to   0.000

Emacs Lisp

(defun maprange (a1 a2 b1 b2 s)
   (+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))
  
(dotimes (i 10)
  (message "%s" (maprange 0.0 10.0 -1.0 0.0 i)))

Erlang

-module(map_range).
-export([map_value/3]).

map_value({A1,A2},{B1,B2},S) ->
    B1 + (S - A1) * (B2 - B1) / (A2 - A1).

ERRE

PROGRAM RANGE

BEGIN
      AL=0   AH=10
      BL=-1  BH=0
      FOR N=0 TO 10 DO
        RANGE=BL+(N-AL)*(BH-BL)/(AH-AL)
        WRITE("### maps to ##.##";N;RANGE)
!        PRINT(N;" maps to ";RANGE)
      END FOR
END PROGRAM
Output:
  0 maps to -1.00
  1 maps to -0.90
  2 maps to -0.80
  3 maps to -0.70
  4 maps to -0.60
  5 maps to -0.50
  6 maps to -0.40
  7 maps to -0.30
  8 maps to -0.20
  9 maps to -0.10
 10 maps to  0.00

Euphoria

function map_range(sequence a, sequence b, atom s)
    return b[1]+(s-a[1])*(b[2]-b[1])/(a[2]-a[1])
end function

for i = 0 to 10 do
    printf(1, "%2g maps to %4g\n", {i, map_range({0,10},{-1,0},i)})
end for
Output:
 0 maps to   -1
 1 maps to -0.9
 2 maps to -0.8
 3 maps to -0.7
 4 maps to -0.6
 5 maps to -0.5
 6 maps to -0.4
 7 maps to -0.3
 8 maps to -0.2
 9 maps to -0.1
10 maps to    0

F#

let map (a1: float) (a2: float) (b1: float) (b2: float) (s: float): float =
    b1 + (s - a1) * (b2 - b1) / (a2 - a1)

let xs = [| for i in 0..10 -> map 0.0 10.0 -1.0 0.0 (float i) |]

for x in xs do printfn "%f" x

Factor

USE: locals
:: map-range ( a1 a2 b1 b2 x -- y )
   x a1 - b2 b1 - * a2 a1 - / b1 + ;

Or:

USING: locals infix ;
:: map-range ( a1 a2 b1 b2 x -- y ) 
   [infix
     b1 + (x - a1) * (b2 - b1) / (a2 - a1)
   infix] ;

Test run:

10 iota [| x | 0 10 -1 0 x map-range ] map . ! { -1 -9/10 -4/5 -7/10 -3/5 -1/2 -2/5 -3/10 -1/5 -1/10 }

Fantom

class FRange
{
  const Float low
  const Float high
  // in constructing a range, ensure the low value is smaller than high
  new make (Float low, Float high)
  {
    this.low = ( low <= high ? low : high )
    this.high = ( low <= high ? high : low )
  }

  // return range as a string
  override Str toStr () { "[$low,$high]" }
  
  // return a point in given range interpolated into this range
  Float remap (Float point, FRange given)
  {
    this.low + (point - given.low) * (this.high - this.low) / (given.high - given.low)
  }
}

class Main
{
  public static Void main ()
  {
    range1 := FRange (0f, 10f)
    range2 := FRange (-1f, 0f)
    11.times |Int n|
    {
      m := range2.remap (n.toFloat, range1)
      echo ("Value $n in ${range1} maps to $m in ${range2}")
    }
  }
}
Output:
Value 0 in [0.0,10.0] maps to -1.0 in [-1.0,0.0]
Value 1 in [0.0,10.0] maps to -0.9 in [-1.0,0.0]
Value 2 in [0.0,10.0] maps to -0.8 in [-1.0,0.0]
Value 3 in [0.0,10.0] maps to -0.7 in [-1.0,0.0]
Value 4 in [0.0,10.0] maps to -0.6 in [-1.0,0.0]
Value 5 in [0.0,10.0] maps to -0.5 in [-1.0,0.0]
Value 6 in [0.0,10.0] maps to -0.4 in [-1.0,0.0]
Value 7 in [0.0,10.0] maps to -0.30000000000000004 in [-1.0,0.0]
Value 8 in [0.0,10.0] maps to -0.19999999999999996 in [-1.0,0.0]
Value 9 in [0.0,10.0] maps to -0.09999999999999998 in [-1.0,0.0]
Value 10 in [0.0,10.0] maps to 0.0 in [-1.0,0.0]

Forth

\ linear interpolation

: lerp ( b2 b1 a2 a1 s -- t )
  fover f-
  frot frot f- f/
  frot frot fswap fover f- frot f*  
  f+ ;

: test   11 0 do  0e -1e 10e 0e i s>f lerp f.  loop ;

There is less stack shuffling if you use origin and range instead of endpoints for intervals. (o = a1, r = a2-a1)

: lerp ( o2 r2 r1 o1 s -- t ) fswap f-  fswap f/  f*  f+ ;

: test   11 0 do  -1e 1e 10e 0e i s>f lerp f.  loop ;

Fortran

Works with: Fortran version 90 and later
program Map
  implicit none
  
  real :: t
  integer :: i

  do i = 0, 10
    t = Maprange((/0.0, 10.0/), (/-1.0, 0.0/), real(i)) 
    write(*,*) i, " maps to ", t
  end do 

contains

function Maprange(a, b, s)
  real :: Maprange
  real, intent(in) :: a(2), b(2), s
 
  Maprange = (s-a(1)) * (b(2)-b(1)) / (a(2)-a(1)) + b(1) 

end function Maprange
end program Map


FreeBASIC

Translation of: Yabasic
Function MapRange(s As Integer, a1 As Integer, a2 As Integer, b1 As Integer, b2 As Integer) As Double
    Return b1+(s-a1)*(b2-b1)/(a2-a1)
End Function

For i As Integer = 0 To 10
    Print Using "## maps to ##.#"; i; MapRange(i,0,10,-1,0)
Next i
Sleep
Output:
 0 maps to -1.0
 1 maps to -0.9
 2 maps to -0.8
 3 maps to -0.7
 4 maps to -0.6
 5 maps to -0.5
 6 maps to -0.4
 7 maps to -0.3
 8 maps to -0.2
 9 maps to -0.1
10 maps to  0.0

Frink

Frink can exactly map to rational numbers so the mapping is round-trippable.

mapRange[s, a1, a2, b1, b2] :=  b1 + (s-a1)(b2-b1)/(a2-a1)

for a = 0 to 10
   println["$a\t" + mapRange[a, 0, 10, -1, 0]]
Output:
0	-1
1	-9/10 (exactly -0.9)
2	-4/5 (exactly -0.8)
3	-7/10 (exactly -0.7)
4	-3/5 (exactly -0.6)
5	-1/2 (exactly -0.5)
6	-2/5 (exactly -0.4)
7	-3/10 (exactly -0.3)
8	-1/5 (exactly -0.2)
9	-1/10 (exactly -0.1)
10	0

Much more impressive, though, is that Frink is a powerful Computer Algebra System (CAS) and can symbolically invert the function so you can map t back to s:

https://frinklang.org/fsp/solve2.fsp?equations=t+%3D+b1+%2B+%28s-a1%29%28b2-b1%29%2F%28a2-a1%29&solveFor=s&f=on&ev=on&sel_a1=S&val_a1=&sel_a2=S&val_a2=&sel_b1=S&val_b1=&sel_b2=S&val_b2=&sel_t=S&val_t=1000+kg&resultAs=

The resulting inverse function is:

inverseMapRange[t, a1, a2, b1, b2] := a1 + a1 b1 (-1 b1 + b2)^-1 + -1 a2 b1 (-1 b1 + b2)^-1 + -1 a1 (-1 b1 + b2)^-1 t + a2 (-1 b1 + b2)^-1 t

FutureBasic

include "NSLog.incl"

local fn MapRange( s as double, a1 as double, a2 as double, b1 as double, b2 as double ) as double
end fn = b1+(s-a1)*(b2-b1)/(a2-a1)

NSInteger i

for i = 0 to 10
NSLog( @"%2d maps to %5.1f", i, fn MapRange( i, 0, 10, -1, 0 ) )
next

HandleEvents

Output:

 0 maps to  -1.0
 1 maps to  -0.9
 2 maps to  -0.8
 3 maps to  -0.7
 4 maps to  -0.6
 5 maps to  -0.5
 6 maps to  -0.4
 7 maps to  -0.3
 8 maps to  -0.2
 9 maps to  -0.1
10 maps to   0.0

GDScript

func mapRange(s:float, a1:float, a2:float, b1:float, b2:float) -> float :
  return b1 + ((b2-b1)/(a2-a1))*(s-a1)

for i in 11 :
  print( "%2d %+.1f" % [i,mapRange(i,0.0,10.0,-1.0,0.0)] )
Output:
 0 -1.0
 1 -0.9
 2 -0.8
 3 -0.7
 4 -0.6
 5 -0.5
 6 -0.4
 7 -0.3
 8 -0.2
 9 -0.1
10 +0.0


Go

include "NSLog.incl"

local fn MapRange( s as double, a1 as double, a2 as double, b1 as double, b2 as double ) as double
end fn = b1+(s-a1)*(b2-b1)/(a2-a1)

NSInteger i

for i = 0 to 10
NSLog( @"%2d maps to %5.1f", i, fn MapRange( i, 0, 10, -1, 0 ) )
next

HandleEvents

Output:

 0 maps to  -1.0
 1 maps to  -0.9
 2 maps to  -0.8
 3 maps to  -0.7
 4 maps to  -0.6
 5 maps to  -0.5
 6 maps to  -0.4
 7 maps to  -0.3
 8 maps to  -0.2
 9 maps to  -0.1
10 maps to   0.0

Go

Basic task

package main

import "fmt"

type rangeBounds struct {
    b1, b2 float64
}

func mapRange(x, y rangeBounds, n float64) float64 {
    return y.b1 + (n - x.b1) * (y.b2 - y.b1) / (x.b2 - x.b1)
}

func main() {
    r1 := rangeBounds{0, 10}
    r2 := rangeBounds{-1, 0}
    for n := float64(0); n <= 10; n += 2 {
        fmt.Println(n, "maps to", mapRange(r1, r2, n))
    }
}
Output:
0 maps to -1
2 maps to -0.8
4 maps to -0.6
6 maps to -0.4
8 maps to -0.19999999999999996
10 maps to 0

Extra credit

First, a function literal replaces the mapping function specified by the basic task. This allows a simpler parameter signature and also allows things to be precomputed for efficiency. newMapRange checks the direction of the first range and if it is decreasing, reverses both ranges. This simplifies an out-of-range check in the function literal. Also, the slope and intercept of the linear function are computed. This allows the range mapping to use the slope intercept formula which is computationally more efficient that the two point formula.

Second, ", ok" is a Go idiom. It takes advantage of Go's multiple return values and multiple assignment to return a success/failure disposition. In the case of this task, the result t is undefined if the input s is out of range.

package main

import "fmt"

type rangeBounds struct {
    b1, b2 float64
}

func newRangeMap(xr, yr rangeBounds) func(float64) (float64, bool) {
    // normalize direction of ranges so that out-of-range test works
    if xr.b1 > xr.b2 {
        xr.b1, xr.b2 = xr.b2, xr.b1
        yr.b1, yr.b2 = yr.b2, yr.b1
    }
    // compute slope, intercept
    m := (yr.b2 - yr.b1) / (xr.b2 - xr.b1)
    b := yr.b1 - m*xr.b1
    // return function literal
    return func(x float64) (y float64, ok bool) {
        if x < xr.b1 || x > xr.b2 {
            return 0, false // out of range
        }
        return m*x + b, true
    }
}

func main() {
    rm := newRangeMap(rangeBounds{0, 10}, rangeBounds{-1, 0})
    for s := float64(-2); s <= 12; s += 2 {
        t, ok := rm(s)
        if ok {
            fmt.Printf("s: %5.2f  t: %5.2f\n", s, t)
        } else {
            fmt.Printf("s: %5.2f  out of range\n", s)
        }
    }
}
Output:
s: -2.00  out of range
s:  0.00  t: -1.00
s:  2.00  t: -0.80
s:  4.00  t: -0.60
s:  6.00  t: -0.40
s:  8.00  t: -0.20
s: 10.00  t:  0.00
s: 12.00  out of range

Groovy

def mapRange(a1, a2, b1, b2, s) {
    b1 + ((s - a1) * (b2 - b1)) / (a2 - a1)
}

(0..10).each { s ->
    println(s + " in [0, 10] maps to " + mapRange(0, 10, -1, 0, s) + " in [-1, 0].")
}
Output:
0 in [0, 10] maps to -1 in [-1, 0].
1 in [0, 10] maps to -0.9 in [-1, 0].
2 in [0, 10] maps to -0.8 in [-1, 0].
3 in [0, 10] maps to -0.7 in [-1, 0].
4 in [0, 10] maps to -0.6 in [-1, 0].
5 in [0, 10] maps to -0.5 in [-1, 0].
6 in [0, 10] maps to -0.4 in [-1, 0].
7 in [0, 10] maps to -0.3 in [-1, 0].
8 in [0, 10] maps to -0.2 in [-1, 0].
9 in [0, 10] maps to -0.1 in [-1, 0].
10 in [0, 10] maps to 0 in [-1, 0].

Haskell

Rather than handling only floating point numbers, the mapping function takes any number implementing the Fractional typeclass, which in our example also includes exact Rational numbers.

import Data.Ratio
import Text.Printf (PrintfType, printf)

-- Map a value from the range [a1,a2] to the range [b1,b2].  We don't check
-- for empty ranges.
mapRange
  :: Fractional a
  => (a, a) -> (a, a) -> a -> a
mapRange (a1, a2) (b1, b2) s = b1 + (s - a1) * (b2 - b1) / (a2 - a1)

main :: IO ()
main
-- Perform the mapping over floating point numbers.
 = do
  putStrLn "---------- Floating point ----------"
  mapM_ (\n -> prtD n . mapRange (0, 10) (-1, 0) $ fromIntegral n) [0 .. 10]
  -- Perform the same mapping over exact rationals.
  putStrLn "---------- Rationals ----------"
  mapM_ (\n -> prtR n . mapRange (0, 10) (-1, 0) $ n % 1) [0 .. 10]
  where
    prtD
      :: PrintfType r
      => Integer -> Double -> r
    prtD = printf "%2d -> %6.3f\n"
    prtR
      :: PrintfType r
      => Integer -> Rational -> r
    prtR n x = printf "%2d -> %s\n" n (show x)
Output:
---------- Floating point ----------
 0 -> -1.000
 1 -> -0.900
 2 -> -0.800
 3 -> -0.700
 4 -> -0.600
 5 -> -0.500
 6 -> -0.400
 7 -> -0.300
 8 -> -0.200
 9 -> -0.100
10 ->  0.000
---------- Rationals ----------
 0 -> (-1) % 1
 1 -> (-9) % 10
 2 -> (-4) % 5
 3 -> (-7) % 10
 4 -> (-3) % 5
 5 -> (-1) % 2
 6 -> (-2) % 5
 7 -> (-3) % 10
 8 -> (-1) % 5
 9 -> (-1) % 10
10 -> 0 % 1

Icon and Unicon

record Range(a, b)

# note, we force 'n' to be real, which means recalculation will 
# be using real numbers, not integers
procedure remap (range1, range2, n : real)
  if n < range2.a | n > range2.b then fail # n out of given range
  return range1.a + (n - range2.a) * (range1.b - range1.a) / (range2.b - range2.a)
end
  
procedure range_string (range)
  return "[" || range.a || ", " || range.b || "]"
end

procedure main ()
  range1 := Range (0, 10)
  range2 := Range (-1, 0)
  # if i is out of range1, then 'remap' fails, so only valid changes are written
  every i := -2 to 12 do {
    if m := remap (range2, range1, i)
      then write ("Value " || i || " in " || range_string (range1) || 
                  " maps to " || m || " in " || range_string (range2))
  }
end

Icon does not permit the type declaration, as Unicon does. For Icon, replace 'remap' with:

procedure remap (range1, range2, n)
  n *:= 1.0
  if n < range2.a | n > range2.b then fail # n out of given range
  return range1.a + (n - range2.a) * (range1.b - range1.a) / (range2.b - range2.a)
end
Output:
Value 0 in [0, 10] maps to -1.0 in [-1, 0]
Value 1 in [0, 10] maps to -0.9 in [-1, 0]
Value 2 in [0, 10] maps to -0.8 in [-1, 0]
Value 3 in [0, 10] maps to -0.7 in [-1, 0]
Value 4 in [0, 10] maps to -0.6 in [-1, 0]
Value 5 in [0, 10] maps to -0.5 in [-1, 0]
Value 6 in [0, 10] maps to -0.4 in [-1, 0]
Value 7 in [0, 10] maps to -0.3 in [-1, 0]
Value 8 in [0, 10] maps to -0.2 in [-1, 0]
Value 9 in [0, 10] maps to -0.1 in [-1, 0]
Value 10 in [0, 10] maps to 0.0 in [-1, 0]

J

maprange=:2 :0
  'a1 a2'=.m
  'b1 b2'=.n
  b1+((y-a1)*b2-b1)%a2-a1
)
NB. this version defers all calculations to runtime, but mirrors exactly the task formulation

Or

maprange=:2 :0
  'a1 a2'=.m
  'b1 b2'=.n
  b1 + ((b2-b1)%a2-a1) * -&a1
)
NB. this version precomputes the scaling ratio

Or, more concisely:

maprange=:{{ ({.n) + (n%&(-/)m) * -&({.m) }}

Example use:

   2 4 maprange 5 11 (2.718282 3 3.141592)
7.15485 8 8.42478

or

   adjust=:2 4 maprange 5 11 NB. save the derived function as a named entity
   adjust 2.718282 3 3.141592
7.15485 8 8.42478

Required example:

   0 10 maprange _1 0 i.11
_1 _0.9 _0.8 _0.7 _0.6 _0.5 _0.4 _0.3 _0.2 _0.1 0

Java

public class Range {
	public static void main(String[] args){
		for(float s = 0;s <= 10; s++){
			System.out.println(s + " in [0, 10] maps to "+ 
					mapRange(0, 10, -1, 0, s)+" in [-1, 0].");
		}
	}
	
	public static double mapRange(double a1, double a2, double b1, double b2, double s){
		return b1 + ((s - a1)*(b2 - b1))/(a2 - a1);
	}
}
Output:
0.0 in [0, 10] maps to -1.0 in [-1, 0].
1.0 in [0, 10] maps to -0.9 in [-1, 0].
2.0 in [0, 10] maps to -0.8 in [-1, 0].
3.0 in [0, 10] maps to -0.7 in [-1, 0].
4.0 in [0, 10] maps to -0.6 in [-1, 0].
5.0 in [0, 10] maps to -0.5 in [-1, 0].
6.0 in [0, 10] maps to -0.4 in [-1, 0].
7.0 in [0, 10] maps to -0.30000000000000004 in [-1, 0].
8.0 in [0, 10] maps to -0.19999999999999996 in [-1, 0].
9.0 in [0, 10] maps to -0.09999999999999998 in [-1, 0].
10.0 in [0, 10] maps to 0.0 in [-1, 0].

The differences in 7, 8, and 9 come from double math. Similar issues show even when using float types.

JavaScript

ES5

// Javascript doesn't have built-in support for ranges
// Insted we use arrays of two elements to represent ranges
var mapRange = function(from, to, s) {
  return to[0] + (s - from[0]) * (to[1] - to[0]) / (from[1] - from[0]);
};

var range = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (var i = 0; i < range.length; i++) {
  range[i] = mapRange([0, 10], [-1, 0], range[i]);
}

console.log(range);
Output:
[-1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.30000000000000004, -0.19999999999999996, -0.09999999999999998, 0]

Extra credit

Here we will use the ECMAScript 5 support for map and the _.range function from Underscore.js.

Library: Underscore.js
var mapRange = function(from, to, s) {
  // mapRange expects ranges generated by _.range
  var a1 = from[0];
  var a2 = from[from.length - 1];
  var b1 = to[0];
  var b2 = to[to.length - 1];
  return b1 + (s - a1) * (b2 - b1) / (a2 - a1);
};

// The range function is exclusive
var fromRange = _.range(0, 11);
var toRange = _.range(-1, 1);

// .map constructs a new array
fromRange = fromRange.map(function(s) {
  return mapRange(fromRange, toRange, s);
});

console.log(fromRange);
Output:
[-1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.30000000000000004, -0.19999999999999996, -0.09999999999999998, 0]

ES6

Composing a solution from generic abstractions:

(() => {
  'use strict';

  // main :: IO ()
  const main = () => {

    // rangeMap :: (Num, Num) -> (Num, Num) -> Num -> Num
    const rangeMap = (a, b) => s => {
      const [a1, a2] = a;
      const [b1, b2] = b;
      // Scaling up an order, and then down, to bypass a potential,
      // precision issue with negative numbers.
      return (((((b2 - b1) * (s - a1)) / (a2 - a1)) * 10) + (10 * b1)) / 10;
    };

    const
      mapping = rangeMap([0, 10], [-1, 0]),
      xs = enumFromTo(0, 10),
      ys = map(mapping, xs),
      zs = map(approxRatio(''), ys);


    const formatted = (x, m, r) => {
      const
        fract = showRatio(r),
        [n, d] = splitOn('/', fract);
      return justifyRight(2, ' ', x.toString()) + '  ->  ' +
        justifyRight(4, ' ', m.toString()) + '   =  ' +
        justifyRight(2, ' ', n.toString()) + '/' + d.toString();
    };

    console.log(
      unlines(zipWith3(formatted, xs, ys, zs))
    );
  };


  // GENERIC FUNCTIONS ----------------------------

  // abs :: Num -> Num
  const abs = Math.abs;

  // Epsilon - > Real - > Ratio
  // approxRatio :: Real -> Real -> Ratio
  const approxRatio = eps => n => {
    const
      gcde = (e, x, y) => {
        const _gcd = (a, b) => (b < e ? a : _gcd(b, a % b));
        return _gcd(abs(x), abs(y));
      },
      c = gcde(Boolean(eps) ? eps : (1 / 10000), 1, abs(n)),
      r = ratio(quot(abs(n), c), quot(1, c));
    return {
      type: 'Ratio',
      n: r.n * signum(n),
      d: r.d
    };
  };

  // enumFromTo :: Int -> Int -> [Int]
  const enumFromTo = (m, n) =>
    Array.from({
      length: 1 + n - m
    }, (_, i) => m + i)

  // gcd :: Int -> Int -> Int
  const gcd = (x, y) => {
    const
      _gcd = (a, b) => (0 === b ? a : _gcd(b, a % b)),
      abs = Math.abs;
    return _gcd(abs(x), abs(y));
  };

  // justifyRight :: Int -> Char -> String -> String
  const justifyRight = (n, cFiller, s) =>
    n > s.length ? (
      s.padStart(n, cFiller)
    ) : s;

  // Returns Infinity over objects without finite length
  // this enables zip and zipWith to choose the shorter
  // argument when one is non-finite, like cycle, repeat etc

  // length :: [a] -> Int
  const length = xs => Array.isArray(xs) ? xs.length : Infinity;

  // map :: (a -> b) -> [a] -> [b]
  const map = (f, xs) => xs.map(f);

  // quot :: Int -> Int -> Int
  const quot = (n, m) => Math.floor(n / m);

  // ratio :: Int -> Int -> Ratio Int
  const ratio = (x, y) => {
    const go = (x, y) =>
      0 !== y ? (() => {
        const d = gcd(x, y);
        return {
          type: 'Ratio',
          'n': quot(x, d), // numerator
          'd': quot(y, d) // denominator
        };
      })() : undefined;
    return go(x * signum(y), abs(y));
  };

  // showRatio :: Ratio -> String
  const showRatio = nd =>
    nd.n.toString() + '/' + nd.d.toString();

  // signum :: Num -> Num
  const signum = n => 0 > n ? -1 : (0 < n ? 1 : 0);

  // splitOn :: String -> String -> [String]
  const splitOn = (pat, src) =>
    src.split(pat);

  // unlines :: [String] -> String
  const unlines = xs => xs.join('\n');

  // zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
  const zipWith3 = (f, xs, ys, zs) =>
    Array.from({
      length: Math.min(length(xs), length(ys), length(zs))
    }, (_, i) => f(xs[i], ys[i], zs[i]));

  // MAIN ---
  return main();
})();
Output:
 0  ->    -1   =  -1/1
 1  ->  -0.9   =  -9/10
 2  ->  -0.8   =  -4/5
 3  ->  -0.7   =  -7/10
 4  ->  -0.6   =  -3/5
 5  ->  -0.5   =  -1/2
 6  ->  -0.4   =  -2/5
 7  ->  -0.3   =  -3/10
 8  ->  -0.2   =  -1/5
 9  ->  -0.1   =  -1/10
10  ->     0   =   0/1

jq

In jq, it is generally preferable to define functions as parameterized filters. In the present case, since the task calls for defining a map, the signature maprange(a;b), where a and b are the two ranges, is appropriate.

# The input is the value to be mapped.
# The ranges, a and b, should each be an array defining the
# left-most and right-most points of the range.
def maprange(a; b):
  b[0] + (((. - a[0]) * (b[1] - b[0])) / (a[1] - a[0])) ;

Example 1: a single value

6 | maprange([0,10]; [-1, 0])

produces:

 -0.4

Example 2: a stream of values

range(0;11) | maprange([0,10]; [-1, 0])

produces:

-1
-0.9
-0.8
-0.7
-0.6
-0.5
-0.4
-0.30000000000000004
-0.19999999999999996
-0.09999999999999998
0

Extra credit

To avoid repeating the same arithmetic, we shall define a filter that handles an array of values all at once, using an inner function and map/1:

def maprange_array(a; b):
  def _helper(a0; b0; factor): b0 + (. - a0) * factor;

  a[0] as $a | b[0] as $b | ((b[1] - b[0]) / (a[1] - a[0])) as $factor
  | map(_helper( $a; $b; $factor) );

Example:

[range(0;11)] | maprange_array([0,10]; [-1, 0])

Julia

Works with: Julia version 0.6
function maprange(s, a, b)
    a₁, a₂ = minimum(a), maximum(a)
    b₁, b₂ = minimum(b), maximum(b)
    return b₁ + (s - a₁) * (b₂ - b₁) / (a₂ - a₁)
end

@show maprange(6, 1:10, -1:0)
@show maprange(0:10, 0:10, -1:0)
Output:
maprange(6, 1:10, -1:0) = -0.4444444444444444
maprange(0:10, 0:10, -1:0) = -1.0:0.1:0.0

K

   f:{[a1;a2;b1;b2;s] b1+(s-a1)*(b2-b1)%(a2-a1)}

   +(a; f[0;10;-1;0]'a:!11)
((0;-1.0)
 (1;-0.9)
 (2;-0.8)
 (3;-0.7)
 (4;-0.6)
 (5;-0.5)
 (6;-0.4)
 (7;-0.3)
 (8;-0.2)
 (9;-0.1)
 (10;0.0))

Kotlin

// version 1.0.6

class FloatRange(override val start: Float, override val endInclusive: Float) : ClosedRange<Float>

fun mapRange(range1: FloatRange, range2: FloatRange, value: Float): Float {
    if (value !in range1) throw IllegalArgumentException("value is not within the first range")
    if (range1.endInclusive == range1.start) throw IllegalArgumentException("first range cannot be single-valued")
    return range2.start + (value - range1.start) * (range2.endInclusive - range2.start) / (range1.endInclusive - range1.start)
}
        
fun main(args: Array<String>) {
    for (i in 0..10) {
        val mappedValue = mapRange(FloatRange(0.0f, 10.0f), FloatRange(-1.0f, 0.0f), i.toFloat())
        println(String.format("%2d  maps to %+4.2f", i, mappedValue))
    }
}
Output:
 0  maps to -1.00
 1  maps to -0.90
 2  maps to -0.80
 3  maps to -0.70
 4  maps to -0.60
 5  maps to -0.50
 6  maps to -0.40
 7  maps to -0.30
 8  maps to -0.20
 9  maps to -0.10
10  maps to +0.00

Lambdatalk

{def maprange
 {lambda {:a0 :a1 :b0 :b1 :s}
  {+ :b0 {/ {* {- :s :a0} {- :b1 :b0}} {- :a1 :a0}}}}}
-> maprange

{maprange 0 10 -1 0 5}
-> -0.5

{S.map {maprange 0 10 -1 0} {S.serie 0 10}}
-> 
0 maps to -1 
1 maps to -0.9 
2 maps to -0.8 
3 maps to -0.7 
4 maps to -0.6 
5 maps to -0.5 
6 maps to -0.4 
7 maps to -0.30000000000000004 
8 maps to -0.19999999999999996 
9 maps to -0.09999999999999998 
10 maps to 0

Lasso

define map_range(
	a1,
	a2,
	b1,
	b2,
	number
) => (decimal(#b1) + (decimal(#number) - decimal(#a1)) * (decimal(#b2) - decimal(#b1)) / (decimal(#a2) - decimal(#a1))) -> asstring(-Precision = 1)

with number in generateSeries(1,10) do {^
	#number
	': '
	map_range( 0, 10, -1, 0, #number)
	'<br />'

^}'
Output:
0: -1.0
1: -0.9
2: -0.8
3: -0.7
4: -0.6
5: -0.5
6: -0.4
7: -0.3
8: -0.2
9: -0.1
10: 0.0

Liberty BASIC

For i = 0 To 10
    Print "f(";i;") maps to ";mapToRange(i, 0, 10, -1, 0)
Next i
End

Function mapToRange(value, inputMin, inputMax, outputMin, outputMax)
  mapToRange = (((value - inputMin) * (outputMax - outputMin)) / (inputMax - inputMin)) + outputMin
End Function
Output:
f(0) maps to -1
f(1) maps to -0.9
f(2) maps to -0.8
f(3) maps to -0.7
f(4) maps to -0.6
f(5) maps to -0.5
f(6) maps to -0.4
f(7) maps to -0.3
f(8) maps to -0.2
f(9) maps to -0.1
f(10) maps to 0

to interpolate :s :a1 :a2 :b1 :b2
  output (:s-:a1) / (:a2-:a1) * (:b2-:b1) + :b1
end

for [i 0 10] [print interpolate :i 0 10 -1 0]

Lua

function map_range( a1, a2, b1, b2, s )
    return b1 + (s-a1)*(b2-b1)/(a2-a1)
end

for i = 0, 10 do
    print( string.format( "f(%d) = %f", i, map_range( 0, 10, -1, 0, i ) ) )
end

M2000 Interpreter

Using Class

module MapRange {
	class Map {
	private:
		a, b, f
	public:
		value (x){
			=.b+(x-.a)*.f
		}
	class:
		module Map (.a,a2,.b,b2) {
			if a2-.a=0 then error "wrong parameters"
			.f<=(b2-.b)/(a2-.a)
		}
	}
	
	m1=Map(0,10, -1, 0)
	for i=0 to 10
		Print i," maps to ";m1(i)
	next
}
MapRange

Using Lambda

module MapRange {
	Map=lambda (a,a2,b,b2) -> {
		if a2-a=0 then error "wrong parameters"
		f=(b2-b)/(a2-a)
		=lambda a,b,f (x)->b+(x-a)*f
	}
	m1=Map(0,10, -1, 0)
	for i=0 to 10
		Print i," maps to ";m1(i)
	next
}
MapRange

Same output for both versions

Output:
 0 maps to -1
 1 maps to -0.9
 2 maps to -0.8
 3 maps to -0.7
 4 maps to -0.6
 5 maps to -0.5
 6 maps to -0.4
 7 maps to -0.3
 8 maps to -0.2
 9 maps to -0.1
10 maps to 0

Maple

Map:=proc(a1,a2,b1,b2,s);
	return (b1+((s-a1)*(b2-b1)/(a2-a1)));
end proc;

for i from 0 to 10 do
	printf("%a  maps to ",i);
	printf("%a\n",Map(0,10,-1,0,i));
end do;

Mathematica/Wolfram Language

Such a function is already built in

Rescale[#,{0,10},{-1,0}]&/@Range[0,10]
Output:
{-1., -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.}

Maxima

maprange(a, b, c, d) := buildq([e: ratsimp(('x - a)*(d - c)/(b - a) + c)],
   lambda([x], e))$

f: maprange(0, 10, -1, 0);

Nemerle

using System;
using System.Console;

module Maprange
{
    Maprange(a : double * double, b : double * double, s : double) : double
    {
        def (a1, a2) = a; def (b1, b2) = b;
        
        b1 + (((s - a1) * (b2 - b1))/(a2 - a1))
    }
    
    Main() : void
    {
        foreach (i in [0 .. 10]) 
            WriteLine("{0, 2:f0} maps to {1:f1}", i, Maprange((0.0, 10.0), (-1.0, 0.0), i));
    }
}

NetRexx

/* NetRexx */
options replace format comments java crossref savelog symbols nobinary

A    = [  0.0, 10.0 ]
B    = [ -1.0,  0.0 ]
incr = 1.0

say 'Mapping ['A[0]',' A[1]'] to ['B[0]',' B[1]'] in increments of' incr':'
loop sVal = A[0] to A[1] by incr
  say '  f('sVal.format(3, 3)') ='  mapRange(A, B, sVal).format(4, 3)
  end sVal

return

method mapRange(a = Rexx[], b = Rexx[], s_) public static
  return mapRange(a[0], a[1], b[0], b[1], s_)

method mapRange(a1, a2, b1, b2, s_) public static
  t_ = b1 + ((s_ - a1) * (b2 - b1) / (a2 - a1))
  return t_
Output:
Mapping [0.0, 10.0] to [-1.0, 0.0] in increments of 1.0: 
  f(  0.000) =   -1.000 
  f(  1.000) =   -0.900 
  f(  2.000) =   -0.800 
  f(  3.000) =   -0.700 
  f(  4.000) =   -0.600 
  f(  5.000) =   -0.500 
  f(  6.000) =   -0.400 
  f(  7.000) =   -0.300 
  f(  8.000) =   -0.200 
  f(  9.000) =   -0.100 
  f( 10.000) =    0.000

Nim

Translation of: Python
import strformat

type FloatRange = tuple[s, e: float]

proc mapRange(a, b: FloatRange; s: float): float =
  b.s + (s - a.s) * (b.e - b.s) / (a.e - a.s)

for i in 0..10:
  let m = mapRange((0.0,10.0), (-1.0, 0.0), float(i))
  echo &"{i:>2} maps to {m:4.1f}"
Output:
 0 maps to -1.0
 1 maps to -0.9
 2 maps to -0.8
 3 maps to -0.7
 4 maps to -0.6
 5 maps to -0.5
 6 maps to -0.4
 7 maps to -0.3
 8 maps to -0.2
 9 maps to -0.1
10 maps to  0.0

Objeck

bundle Default {
  class Range {
    function : MapRange(a1:Float, a2:Float, b1:Float, b2:Float, s:Float) ~ Float {
      return b1 + (s-a1)*(b2-b1)/(a2-a1);
    }

    function : Main(args : String[]) ~ Nil {
      "Mapping [0,10] to [-1,0] at intervals of 1:"->PrintLine();
      for(i := 0.0; i <= 10.0; i += 1;) {
        IO.Console->Print("f(")->Print(i->As(Int))->Print(") = ")->PrintLine(MapRange(0.0, 10.0, -1.0, 0.0, i));
      };
    }
  }
}
Output:
Mapping [0,10] to [-1,0] at intervals of 1:
f(0) = -1
f(1) = -0.9
f(2) = -0.8
f(3) = -0.7
f(4) = -0.6
f(5) = -0.5
f(6) = -0.4
f(7) = -0.3
f(8) = -0.2
f(9) = -0.1
f(10) = 0

OCaml

let map_range (a1, a2) (b1, b2) s =
  b1 +. ((s -. a1) *. (b2 -. b1) /. (a2 -. a1))
 
let () =
  print_endline "Mapping [0,10] to [-1,0] at intervals of 1:";
  for i = 0 to 10 do
    Printf.printf "f(%d) = %g\n" i (map_range (0.0, 10.0) (-1.0, 0.0) (float i))
  done
Output:
Mapping [0,10] to [-1,0] at intervals of 1:
f(0) = -1
f(1) = -0.9
f(2) = -0.8
f(3) = -0.7
f(4) = -0.6
f(5) = -0.5
f(6) = -0.4
f(7) = -0.3
f(8) = -0.2
f(9) = -0.1
f(10) = 0

If range mapping is used in a heavy computational task we can reduce the number of calculations made using partial application and currying:

let map_range (a1, a2) (b1, b2) =
  let v = (b2 -. b1) /. (a2 -. a1) in
  function s ->
    b1 +. ((s -. a1) *. v)
 
let () =
  print_endline "Mapping [0,10] to [-1,0] at intervals of 1:";
  let p = (map_range (0.0, 10.0) (-1.0, 0.0)) in
  for i = 0 to 10 do
    Printf.printf "f(%d) = %g\n" i (p (float i))
  done

Oforth

: mapRange(p1, p2, s) 
   s p1 first - p2 second p2 first - * p1 second p1 first - asFloat / 
   p2 first + ;
Output:
Interval newFromToStep(0, 10, 0.5) map(#[ mapRange([0, 10], [ -1, 0 ])]) println
[-1, -0.95, -0.9, -0.85, -0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.45, -0.4, -0.35,
-0.3, -0.25, -0.2, -0.15, -0.1, -0.05, 0]

PARI/GP

Usage (e.g.): map([1,10],[0,5],8.)

map(r1,r2,x)=r2[1]+(x-r1[1])*(r2[2]-r2[1])/(r1[2]-r1[1])

Pascal

Program Map(output);

function MapRange(fromRange, toRange: array of real; value: real): real;
  begin
    MapRange := (value-fromRange[0]) * (toRange[1]-toRange[0]) / (fromRange[1]-fromRange[0]) + toRange[0];
  end;

var
  i: integer;
begin
  for i := 0 to 10 do
    writeln (i, ' maps to: ', MapRange([0.0, 10.0], [-1.0, 0.0], i):4:2);
end.
Output:
:> ./MapRange
0 maps to: -1.00
1 maps to: -0.90
2 maps to: -0.80
3 maps to: -0.70
4 maps to: -0.60
5 maps to: -0.50
6 maps to: -0.40
7 maps to: -0.30
8 maps to: -0.20
9 maps to: -0.10
10 maps to: 0.00

improvement doing many calculations

Tested with freepascal_32 2.6.4 .Pushing all data over the stack takes quite a long time. Precaltulating the scalefactor helps too.

Time relation doing 1E7 calculations

Org/ const / tMr

double  : 267/177/107 .. 25/16/10

extended: 363/193/123 .. 30/15/10

Output as above.

Program Map(output);

type
  real = double;
  tRange = Array [0..1] of real;
  tMapRec = record
              mrFrom,
              mrTo : tRange;
              mrScale : real
            end;

function InitRange(rfrom,rTo:real):tRange;
begin
  InitRange[0] :=rfrom;
  InitRange[1] :=rTo;
end;

function InitMapRec(const fromRange, toRange: tRange):tMapRec;
begin
  With InitMapRec do
  Begin
    mrFrom := fromRange;
    mrTo   := toRange;
    mrScale := (toRange[1]-toRange[0]) / (fromRange[1]-fromRange[0]);
  end;
end;

function MapRecRange(const value: real;var MR :tMapRec): real;
begin
  with MR do
    MapRecRange := (value-mrFrom[0]) * mrScale + mrTo[0];
end;

function MapRange(const value: real;const fromRange, toRange: tRange): real;
begin
  MapRange := (value-fromRange[0]) * (toRange[1]-toRange[0]) / (fromRange[1]-fromRange[0]) + toRange[0];
end;

var
  value:real;
  rFrom,rTo : tRange;
  mr : tMapRec;
  i: LongInt;

begin
  rFrom:= InitRange(  0, 10);
  rTo  := InitRange( -1,  0);
  mr:= InitMapRec(rFrom,rTo);

  for i := 0 to 10 do
  Begin
    value := i;
    writeln (i:4, ' maps to: ', MapRange(value,rFrom, rTo):10:6,
                                  MapRecRange(value,mr):10:6);
  end;
end.

Perl

#!/usr/bin/perl -w
use strict ;

sub mapValue {
   my ( $range1 , $range2 , $number ) = @_ ;
   return ( $range2->[ 0 ] +
      (( $number - $range1->[ 0 ] ) * ( $range2->[ 1 ] - $range2->[ 0 ] ) ) / ( $range1->[ -1 ] 
      - $range1->[ 0 ] ) ) ;
}
my @numbers = 0..10 ;
my @interval = ( -1 , 0 ) ;
print "The mapped value for $_ is " . mapValue( \@numbers , \@interval , $_ ) . " !\n" foreach @numbers ;
Output:
The mapped value for 0 is -1 !
The mapped value for 1 is -0.9 !
The mapped value for 2 is -0.8 !
The mapped value for 3 is -0.7 !
The mapped value for 4 is -0.6 !
The mapped value for 5 is -0.5 !
The mapped value for 6 is -0.4 !
The mapped value for 7 is -0.3 !
The mapped value for 8 is -0.2 !
The mapped value for 9 is -0.1 !
The mapped value for 10 is 0 !

Phix

with javascript_semantics
function map_range(atom s, a1, a2, b1, b2)
    return b1+(s-a1)*(b2-b1)/(a2-a1)
end function
 
for i=0 to 10 by 2 do
    printf(1,"%2d : %g\n",{i,map_range(i,0,10,-1,0)})
end for
Output:
 0 : -1
 2 : -0.8
 4 : -0.6
 6 : -0.4
 8 : -0.2
10 : 0

PicoLisp

(scl 1)

(de mapRange (Val A1 A2 B1 B2)
   (+ B1 (*/ (- Val A1) (- B2 B1) (- A2 A1))) )


(for Val (range 0 10.0 1.0)
   (prinl
      (format (mapRange Val 0 10.0 -1.0 0) *Scl) ) )
Output:
-1.0
-0.9
-0.8
-0.7
-0.6
-0.5
-0.4
-0.3
-0.2
-0.1
0.0

PL/I

map: procedure options (main); /* 24/11/2011 */
   declare (a1, a2, b1, b2) float;
   declare d fixed decimal (3,1);

   do d = 0 to 10 by 0.9, 10;
      put skip edit ( d, ' maps to ', map(0, 10, -1, 0, d) ) (f(5,1), a, f(10,6));
   end;

map: procedure (a1, a2, b1, b2, s) returns (float);
   declare (a1, a2, b1, b2, s) float;
   return (b1 + (s - a1)*(b2 - b1) / (a2 - a1) );
end map;
end map;
Output:
  0.0 maps to  -1.000000
  0.9 maps to  -0.910000
  1.8 maps to  -0.820000
  2.7 maps to  -0.730000
  3.6 maps to  -0.640000
  4.5 maps to  -0.550000
  5.4 maps to  -0.460000
  6.3 maps to  -0.370000
  7.2 maps to  -0.280000
  8.1 maps to  -0.190000
  9.0 maps to  -0.100000
  9.9 maps to  -0.010000
 10.0 maps to   0.000000

PowerShell

function Group-Range
{
    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    Param
    (
        [Parameter(Mandatory=$true,
                   Position=0)]
        [ValidateCount(2,2)]
        [double[]]
        $Range1,

        [Parameter(Mandatory=$true,
                   Position=1)]
        [ValidateCount(2,2)]
        [double[]]
        $Range2,

        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   Position=2)]
        [double]
        $Map
    )

    Process
    {
        foreach ($number in $Map)
        {
            [PSCustomObject]@{
                Index   = $number
                Mapping = $Range2[0] + ($number - $Range1[0]) * ($Range2[0] - $Range2[1]) / ($Range1[0] - $Range1[1])
            }
        }
    }
}
0..10 | Group-Range (0,10) (-1,0)
Output:
Index Mapping
----- -------
    0      -1
    1    -0.9
    2    -0.8
    3    -0.7
    4    -0.6
    5    -0.5
    6    -0.4
    7    -0.3
    8    -0.2
    9    -0.1
   10       0

PureBasic

Structure RR
  a.f
  b.f
EndStructure

Procedure.f MapRange(*a.RR, *b.RR, s)
  Protected.f a1, a2, b1, b2 
  a1=*a\a:  a2=*a\b
  b1=*b\a:  b2=*b\b
  ProcedureReturn b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
EndProcedure


;- Test the function
If OpenConsole()
  Define.RR Range1, Range2
  Range1\a=0: Range1\b=10
  Range2\a=-1:Range2\b=0
  ;
  For i=0 To 10
    PrintN(RSet(Str(i),2)+" maps to "+StrF(MapRange(@Range1, @Range2, i),1))
  Next
EndIf
 0 maps to -1.0
 1 maps to -0.9
 2 maps to -0.8
 3 maps to -0.7
 4 maps to -0.6
 5 maps to -0.5
 6 maps to -0.4
 7 maps to -0.3
 8 maps to -0.2
 9 maps to -0.1
10 maps to 0.0

Python

>>> def maprange( a, b, s):
	(a1, a2), (b1, b2) = a, b
	return  b1 + ((s - a1) * (b2 - b1) / (a2 - a1))

>>> for s in range(11):
	print("%2g maps to %g" % (s, maprange( (0, 10), (-1, 0), s)))

	
 0 maps to -1
 1 maps to -0.9
 2 maps to -0.8
 3 maps to -0.7
 4 maps to -0.6
 5 maps to -0.5
 6 maps to -0.4
 7 maps to -0.3
 8 maps to -0.2
 9 maps to -0.1
10 maps to 0

Because of Pythons strict, dynamic, typing rules for numbers the same function can give answers as fractions:

>>> from fractions import Fraction
>>> for s in range(11):
	print("%2g maps to %s" % (s, maprange( (0, 10), (-1, 0), Fraction(s))))

	
 0 maps to -1
 1 maps to -9/10
 2 maps to -4/5
 3 maps to -7/10
 4 maps to -3/5
 5 maps to -1/2
 6 maps to -2/5
 7 maps to -3/10
 8 maps to -1/5
 9 maps to -1/10
10 maps to 0
>>>

Quackery

As Quackery does not support reals (or floating point), the function takes the argument s as a decimal string, and returns the result, t as a rational number.

  [ $ "bigrat.qky" loadfile ] now!

  [ do over -
    2swap
    do over -
    unrot
    dip [ $->v drop ]
    n->v v-
    rot n->v v/
    rot n->v v*
    rot n->v v+ ]     is maprange ( $ [ [ --> n/d )

  $ "0 1 2 3 4 5 6 7 8 9 10"
  nest$
  witheach
    [ dup echo$ say " maps to "
      ' [ 0 10 ] ' [ -1 0 ] maprange
      7 point$ echo$ cr ]
Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

R

tRange <- function(aRange, bRange, s)
{
  #Guard clauses. We could write some proper error messages, but this is all we really need.
  stopifnot(length(aRange) == 2, length(bRange) == 2,
            is.numeric(aRange), is.numeric(bRange), is.numeric(s),
            s >= aRange[1], s <= aRange[2])
  bRange[1] + ((s - aRange[1]) * (bRange[2] - bRange[1])) / (aRange[2] - aRange[1])
}
data.frame(s = 0:10, t = sapply(0:10, tRange, aRange = c(0, 10), bRange = c(-1, 0)))
Output:
    s    t
1   0 -1.0
2   1 -0.9
3   2 -0.8
4   3 -0.7
5   4 -0.6
6   5 -0.5
7   6 -0.4
8   7 -0.3
9   8 -0.2
10  9 -0.1
11 10  0.0

Racket

#lang racket

(define (make-range-map a1 a2 b1 b2)
  ;; returns a mapping function, doing computing the differences in
  ;; advance so it's fast
  (let ([a (- a2 a1)] [b (- b2 b1)])
    (λ(s) (exact->inexact (+ b1 (/ (* (- s a1) b) a))))))

(define map (make-range-map 0 10 -1 0))
(for ([i (in-range 0 11)]) (printf "~a --> ~a\n" i (map i)))
Output:
0 --> -1.0
1 --> -0.9
2 --> -0.8
3 --> -0.7
4 --> -0.6
5 --> -0.5
6 --> -0.4
7 --> -0.3
8 --> -0.2
9 --> -0.1
10 --> 0.0

Raku

(formerly Perl 6) Return a closure that does the mapping without have to supply the ranges every time.

sub getmapper(Range $a, Range  $b) {
  my ($a1, $a2) = $a.bounds;
  my ($b1, $b2) = $b.bounds;
  return -> $s { $b1 + (($s-$a1) * ($b2-$b1) / ($a2-$a1)) }
}

my &mapper = getmapper(0 .. 10, -1 .. 0);
for ^11 -> $x {say "$x maps to &mapper($x)"}
Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

ReScript

let map_range = ((a1, a2), (b1, b2), s) => {
  b1 +. ((s -. a1) *. (b2 -. b1) /. (a2 -. a1))
}

Js.log("Mapping [0,10] to [-1,0] at intervals of 1:")

for i in 0 to 10 {
  Js.log("f(" ++ Js.String.make(i) ++ ") = " ++
    Js.String.make(map_range((0.0, 10.0), (-1.0, 0.0), float(i))))
}
<!DOCTYPE html>
<html>
<head>
<title>ReScript: Map_range</title>
<meta charset="UTF-8"/>
<style rel="stylesheet" type="text/css">
body { color:#EEE; background-color:#888; }
</style>
<script>var exports = {};</script>
<script src="./maprange.js"></script>
</head>
<body>

</body>
</html>
Output:
Mapping [0,10] to [-1,0] at intervals of 1:
f(0) = -1
f(1) = -0.9
f(2) = -0.8
f(3) = -0.7
f(4) = -0.6
f(5) = -0.5
f(6) = -0.4
f(7) = -0.30000000000000004
f(8) = -0.19999999999999996
f(9) = -0.09999999999999998
f(10) = 0

REXX

(The first three REXX versions don't differ idiomatically that much, but differ mostly just in style.)

The first three versions support different increments   (the   inc   variable)   and an   A   range that is decreasing in values
(that is, the 2nd number [usually the high] in the range is less than the first number in the range [usually the low]).   Also,
the   BY   (increment)   is automatically adjusted   (either   upwards   or   downwards).   Also, both sets of numbers in the
output are aligned  (vertically).

version 1

/*REXX program maps and displays a  range of numbers from  one range  to  another range.*/
rangeA =   0   10                                      /*or:   rangeA =   '  0  10 '    */
rangeB =  -1    0                                      /*or:   rangeB =   " -1   0 "    */
parse  var   rangeA  L  H
inc= 1
          do j=L  to H  by inc * (1 - 2 * sign(H<L) )  /*BY:   either   +inc  or  -inc  */
          say right(j, 9)      ' maps to '      mapR(rangeA, rangeB, j)
          end   /*j*/
exit                                                   /*stick a fork in it, we're done.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
mapR: procedure; parse arg a1 a2,b1 b2,s;$=b1+(s-a1)*(b2-b1)/(a2-a1);return left('',$>=0)$
output:
        0  maps to  -1
        1  maps to  -0.9
        2  maps to  -0.8
        3  maps to  -0.7
        4  maps to  -0.6
        5  maps to  -0.5
        6  maps to  -0.4
        7  maps to  -0.3
        8  maps to  -0.2
        9  maps to  -0.1
       10  maps to   0

version 2

This version demonstrates an increment (inc) of   1/2   instead of the usual unity.

Note that this REXX version also uses a different   rangeA   numbers   (they are reversed).

/*REXX program maps and displays a  range of numbers from  one range  to  another range.*/
rangeA =  10   0                                       /*or:   rangeA =   '  0  10 '    */
rangeB =  -1   0                                       /*or:   rangeB =   " -1   0 "    */
parse  var   rangeA  L  H
inc= 1/2
          do j=L  to H  by inc * (1 - 2 * sign(H<L) )  /*BY:   either   +inc  or  -inc  */
          say right(j, 9)      ' maps to '      mapR(rangeA, rangeB, j)
          end   /*j*/
exit                                                   /*stick a fork in it, we're done.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
mapR: procedure; parse arg a1 a2,b1 b2,s;$=b1+(s-a1)*(b2-b1)/(a2-a1);return left('',$>=0)$
output:
        0  maps to   0
      0.5  maps to  -0.05
      1.0  maps to  -0.1
      1.5  maps to  -0.15
      2.0  maps to  -0.2
      2.5  maps to  -0.25
      3.0  maps to  -0.3
      3.5  maps to  -0.35
      4.0  maps to  -0.4
      4.5  maps to  -0.45
      5.0  maps to  -0.5
      5.5  maps to  -0.55
      6.0  maps to  -0.6
      6.5  maps to  -0.65
      7.0  maps to  -0.7
      7.5  maps to  -0.75
      8.0  maps to  -0.8
      8.5  maps to  -0.85
      9.0  maps to  -0.9
      9.5  maps to  -0.95
     10.0  maps to  -1

version 3

This REXX version used a function that calculates and also displays the range mapping.

/*REXX program maps and displays a  range of numbers from  one range  to  another range.*/
rangeA =   0   10
rangeB =  -1    0
inc = 1
call mapR rangeA, rangeB, inc
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
mapR: procedure;  parse arg a1 a2, b1 b2, inc    /* [↓]  BY  is  either   +inc  or -inc.*/
                     do s=a1   to a2   by  inc  *  (1  -  2  *  sign(a2 < a1) )
                     t= b1 + (s-a1) * (b2-b1) / (a2-a1)
                     say right(s, 9)        ' maps to'          left('', t>=0)      t
                     end   /*s*/
      return                                     /* [↑]  LEFT··· aligns non─negative #'s*/
output   is identical to the 1st REXX version.



Version 4

/*REXX program maps a number from one range to another range.           */
/* 31.10.2013 Walter Pachl   */
/*                  'translated' from an older version 1 without using Procedure */
  do j=0  to 10
    say right(j,3)   ' maps to '   mapRange(0,10,-1,0,j)
    end
exit                                   
/*──────────────────────────────────MAPRANGE subroutine─────────────────*/
mapRange: return arg(3)+(arg(5)-arg(1))*(arg(4)-arg(3))/(arg(2)-arg(1))
/* Arguments are arg a1,a2,b1,b2,x */
Output:
  0  maps to  -1
  1  maps to  -0.9
  2  maps to  -0.8
  3  maps to  -0.7
  4  maps to  -0.6
  5  maps to  -0.5
  6  maps to  -0.4
  7  maps to  -0.3
  8  maps to  -0.2
  9  maps to  -0.1
 10  maps to  0

Ring

# Project : Map range

decimals(1)
al = 0 
ah = 10
bl = -1 
bh = 0
for n = 0 to 10
     see "" + n + " maps to " + maprange(al, bl, n) + nl
next
 
func maprange(al, bl, s)
       return bl + (s - al) * (bh - bl) / (ah - al)

Output:

0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

RPL

Ranges are entered as complex numbers to ease input and shorten code

Works with: Halcyon Calc version 4.2.7
RPL code Comment
 ≪  → ra rb s
    ≪ rb ra - DUP RE SWAP IM /
      s ra RE - * rb RE + 
 ≫ ≫  'MAP' STO
( (a1, a2) (b1, b2) s -- t )
Get (b2 - b1)/(a2 - a1)
Multiply by (s - a1) and add b1
 
Input:
(0,10) (-1,0) 0 MAP
(0,10) (-1,0) 4 MAP
(0,10) (-1,0) 10 MAP
Output:
3: -1
2: -0.6
1: 0

Basic RPL code

No specific data structure, no local variable, full stack calculation. Shorter, but less practical in use and difficult to read.

≪ SWAP 3 PICK -
   SWAP 5 PICK - *
   ROT 4 ROLL - / +
≫ 'MAP' STO
Input:
0 10 -1 0 0 MAP
0 10 -1 0 4 MAP
0 10 -1 0 10 MAP
Output:
3: -1
2: -0.6
1: 0

Ruby

def map_range(a, b, s)
  af, al, bf, bl = a.first, a.last, b.first, b.last
  bf + (s - af)*(bl - bf).quo(al - af)
end

(0..10).each{|s| puts "%s maps to %g" % [s, map_range(0..10, -1..0, s)]}

Numeric#quo does floating point division.

Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

To use rational arithmetic, delete s *= 1.0 and either require 'rational', or use Ruby 1.9 (which has Rational in the core library).

(0..10).each do |s|
  puts "%s maps to %s" % [s, map_range(0..10, -1..0, s)]
end
Output:

using rational arithmetic

0 maps to -1/1
1 maps to -9/10
2 maps to -4/5
3 maps to -7/10
4 maps to -3/5
5 maps to -1/2
6 maps to -2/5
7 maps to -3/10
8 maps to -1/5
9 maps to -1/10
10 maps to 0/1

Rust

use std::ops::{Add, Sub, Mul, Div};

fn map_range<T: Copy>(from_range: (T, T), to_range: (T, T), s: T) -> T 
    where T: Add<T, Output=T> +
             Sub<T, Output=T> +
             Mul<T, Output=T> +
             Div<T, Output=T>
{
    to_range.0 + (s - from_range.0) * (to_range.1 - to_range.0) / (from_range.1 - from_range.0)
}

fn main() {
    let input: Vec<f64> = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
    let result = input.into_iter()
        .map(|x| map_range((0.0, 10.0), (-1.0, 0.0), x))
        .collect::<Vec<f64>>();
    print!("{:?}", result);
}
Output:
[-1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.30000000000000004, -0.19999999999999996, -0.09999999999999998, 0]

Scala

def mapRange(a1:Double, a2:Double, b1:Double, b2:Double, x:Double):Double=b1+(x-a1)*(b2-b1)/(a2-a1)

for(i <- 0 to 10)
  println("%2d in [0, 10] maps to %5.2f in [-1, 0]".format(i, mapRange(0,10, -1,0, i)))
Output:
 0 in [0, 10] maps to -1,00 in [-1, 0]
 1 in [0, 10] maps to -0,90 in [-1, 0]
 2 in [0, 10] maps to -0,80 in [-1, 0]
 3 in [0, 10] maps to -0,70 in [-1, 0]
 4 in [0, 10] maps to -0,60 in [-1, 0]
 5 in [0, 10] maps to -0,50 in [-1, 0]
 6 in [0, 10] maps to -0,40 in [-1, 0]
 7 in [0, 10] maps to -0,30 in [-1, 0]
 8 in [0, 10] maps to -0,20 in [-1, 0]
 9 in [0, 10] maps to -0,10 in [-1, 0]
10 in [0, 10] maps to  0,00 in [-1, 0]

Seed7

$ include "seed7_05.s7i";
  include "float.s7i";

const func float: mapRange (in float: a1, in float: a2, in float: b1, in float: b2, ref float: s) is
    return b1 + (s-a1)*(b2-b1)/(a2-a1);

const proc: main is func
  local
    var integer: number is 0;
  begin
    writeln("Mapping [0,10] to [-1,0] at intervals of 1:");
    for number range 0 to 10 do
      writeln("f(" <& number <& ") = " <& mapRange(0.0, 10.0, -1.0, 0.0, flt(number)) digits 1);
    end for;
  end func;
Output:
Mapping [0,10] to [-1,0] at intervals of 1:
f(0) = -1.0
f(1) = -0.9
f(2) = -0.8
f(3) = -0.7
f(4) = -0.6
f(5) = -0.5
f(6) = -0.4
f(7) = -0.3
f(8) = -0.2
f(9) = -0.1
f(10) = 0.0

Sidef

func map_range(a, b, x) {
    var (a1, a2, b1, b2) = (a.bounds, b.bounds);
    x-a1 * b2-b1 / a2-a1 + b1;
}

var a = 0..10;
var b = -1..0;

for x in a {
    say "#{x} maps to #{map_range(a, b, x)}";
}
Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

SparForte

As a structured script.

#!/usr/local/bin/spar
pragma annotate( summary, "mapping" )
       @( description, "The task is to write a function/subroutine/... that takes" )
       @( description, "two ranges and a real number, and returns the mapping of" )
       @( description, "the real number from the first to the second range. Use" )
       @( description, "this function to map values from the range [0, 10] to the" )
       @( description, "range [-1, 0]." )
       @( see_also, "http://rosettacode.org/wiki/Map_range" )
       @( author, "Ken O. Burtch" );
pragma license( unrestricted );

pragma restriction( no_external_commands );

procedure mapping is
   type first_range  is new float;
   type second_range is new float;
   -- Spar doesn't implement ranges so we'll use constants
   first_range_first : constant first_range := 0.0;
   first_range_last : constant first_range := 10.0;
   second_range_first : constant second_range := -1.0;
   second_range_last : constant second_range := 0.0;

   function translate (first_range_value : first_range) return second_range is
      b1 : constant float := float( second_range_first );
      b2 : constant float := float( second_range_last );
      a1 : constant float := float( first_range_first );
      a2 : constant float := float( first_range_last );
      result : float;
   begin
      result := b1 + (float (first_range_value) - a1) * (b2 - b1) / (a2 - a1);
      return second_range(result);
   end translate;

   function translate_back (second_range_value : second_range) return first_range is
      b1 : constant float := float (first_range_first);
      b2 : constant float := float (first_range_last);
      a1 : constant float := float (second_range_first);
      a2 : constant float := float (second_range_last);
      result : float;
   begin
      result := b1 + (float (second_range_value) - a1) * (b2 - b1) / (a2 - a1);
      return first_range (result);
   end translate_back;

   test_value            : first_range := first_range_first;
   translated_value      : second_range;
   translated_back_value : first_range;
begin
   loop
      translated_value := translate( test_value );
      translated_back_value := translate_back( translated_value );

      ? strings.image(test_value) & " maps to: "
                          & strings.image (translated_value);
      ? strings.image(translated_value) & " maps back to: "
                          & strings.image (translated_back_value);
      exit when test_value = first_range_last;
      test_value := @ + 1.0;
   end loop;
end mapping;
Output:
$ spar mapping.sp
 0.0 maps to: -1.00000000000000E+00
-1.00000000000000E+00 maps back to:  0.00000000000000E+00
 1.00000000000000E+00 maps to: -9.00000000000000E-01
-9.00000000000000E-01 maps back to:  1.00000000000000E+00
 2.00000000000000E+00 maps to: -8.00000000000000E-01
-8.00000000000000E-01 maps back to:  2.00000000000000E+00
 3.00000000000000E+00 maps to: -7.00000000000000E-01
-7.00000000000000E-01 maps back to:  3.00000000000000E+00
 4.00000000000000E+00 maps to: -6.00000000000000E-01
-6.00000000000000E-01 maps back to:  4.00000000000000E+00
 5.00000000000000E+00 maps to: -5.00000000000000E-01
-5.00000000000000E-01 maps back to:  5.00000000000000E+00
 6.00000000000000E+00 maps to: -4.00000000000000E-01
-4.00000000000000E-01 maps back to:  6.00000000000000E+00
 7.00000000000000E+00 maps to: -3.00000000000000E-01
-3.00000000000000E-01 maps back to:  7.00000000000000E+00
 8.00000000000000E+00 maps to: -2.00000000000000E-01
-2.00000000000000E-01 maps back to:  8.00000000000000E+00
 9.00000000000000E+00 maps to: -1.00000000000000E-01
-1.00000000000000E-01 maps back to:  9.00000000000000E+00
 1.00000000000000E+01 maps to:  0.00000000000000E+00
 0.00000000000000E+00 maps back to:  1.00000000000000E+01

Stata

The following program will map a variable to a new variable. It accepts if and in conditions.

program define maprange
	version 15.1
	syntax varname(numeric) [if] [in], ///
		from(numlist min=2 max=2) to(numlist min=2 max=2) ///
		GENerate(name) [REPLACE]
	tempname a b c d h
	sca `a'=`:word 1 of `from''
	sca `b'=`:word 2 of `from''
	sca `c'=`:word 1 of `to''
	sca `d'=`:word 2 of `to''
	sca `h'=(`d'-`c')/(`b'-`a')
	cap confirm variable `generate'
	if "`replace'"=="replace" & !_rc {
		qui replace `generate'=(`varlist'-`a')*`h'+`c' `if' `in'
	}
	else {
		if "`replace'"=="replace" {
			di in gr `"(note: variable `generate' not found)"'
		}
		qui gen `generate'=(`varlist'-`a')*`h'+`c' `if' `in'
	}
end

Example

clear
set obs 11
gen x=_n-1
maprange x if mod(x,2)==0, gen(y) from(0 10) to(-10 10)
maprange x if mod(x,2)!=0, gen(y) from(0 10) to(-100 100) replace
list

Output

     +----------+
     |  x     y |
     |----------|
  1. |  0   -10 |
  2. |  1   -80 |
  3. |  2    -6 |
  4. |  3   -40 |
  5. |  4    -2 |
     |----------|
  6. |  5     0 |
  7. |  6     2 |
  8. |  7    40 |
  9. |  8     6 |
 10. |  9    80 |
     |----------|
 11. | 10    10 |
     +----------+

Swift

import Foundation

func mapRanges(_ r1: ClosedRange<Double>, _ r2: ClosedRange<Double>, to: Double) -> Double {
  let num = (to - r1.lowerBound) * (r2.upperBound - r2.lowerBound)
  let denom = r1.upperBound - r1.lowerBound
  
  return r2.lowerBound + num / denom
}

for i in 0...10 {
  print(String(format: "%2d maps to %5.2f", i, mapRanges(0...10, -1...0, to: Double(i))))
}
Output:
 0 maps to -1.00
 1 maps to -0.90
 2 maps to -0.80
 3 maps to -0.70
 4 maps to -0.60
 5 maps to -0.50
 6 maps to -0.40
 7 maps to -0.30
 8 maps to -0.20
 9 maps to -0.10
10 maps to  0.00

Tcl

package require Tcl 8.5
proc rangemap {rangeA rangeB value} {
    lassign $rangeA a1 a2
    lassign $rangeB b1 b2
    expr {$b1 + ($value - $a1)*double($b2 - $b1)/($a2 - $a1)}
}

Demonstration (using a curried alias to bind the ranges mapped from and to):

interp alias {} demomap {} rangemap {0 10} {-1 0}
for {set i 0} {$i <= 10} {incr i} {
    puts [format "%2d -> %5.2f" $i [demomap $i]]
}
Output:
 0 -> -1.00
 1 -> -0.90
 2 -> -0.80
 3 -> -0.70
 4 -> -0.60
 5 -> -0.50
 6 -> -0.40
 7 -> -0.30
 8 -> -0.20
 9 -> -0.10
10 ->  0.00

Ursala

The function f is defined using pattern matching and substitution, taking a pair of pairs of interval endpoints and a number as parameters, and returning a number.

#import flo

f((("a1","a2"),("b1","b2")),"s") = plus("b1",div(minus("s","a1"),minus("a2","a1")))

#cast %eL

test = f* ((0.,10.),(-1.,0.))-* ari11/0. 10.
Output:
<
   -1.000000e+00,
   -9.000000e-01,
   -8.000000e-01,
   -7.000000e-01,
   -6.000000e-01,
   -5.000000e-01,
   -4.000000e-01,
   -3.000000e-01,
   -2.000000e-01,
   -1.000000e-01,
   0.000000e+00>

A more idiomatic way is to define f as a second order function

f(("a1","a2"),("b1","b2")) "s" = ...

with the same right hand side as above, so that it takes a pair of intervals and returns a function mapping numbers in one interval to numbers in the other.

An even more idiomatic way is to use the standard library function plin, which takes an arbitrarily long list of interval endpoints and returns a piecewise linear interpolation function.

Vala

double map_range(double s, int a1, int a2, int b1, int b2) {
  return b1+(s-a1)*(b2-b1)/(a2-a1);
} 

void main() { 
  for (int s = 0; s < 11; s++){
    print("%2d maps to %5.2f\n", s, map_range(s, 0, 10, -1, 0));
  }
}
Output:
 0 maps to -1.00
 1 maps to -0.90
 2 maps to -0.80
 3 maps to -0.70
 4 maps to -0.60
 5 maps to -0.50
 6 maps to -0.40
 7 maps to -0.30
 8 maps to -0.20
 9 maps to -0.10
10 maps to  0.00

WDTE

let mapRange r1 r2 s =>
    +
        (at r2 0)
        (/
            (*
                (-
                    s
                    (at r1 0)
                )
                (-
                    (at r2 1)
                    (at r2 0)
                )
            )
            (-
                (at r1 1)
                (at r1 0)
            )
        )
    ;

let s => import 'stream';
let str => import 'strings';

s.range 10
-> s.map (@ enum v => [v; mapRange [0; 10] [-1; 0] v])
-> s.map (@ print v => str.format '{} -> {}' (at v 0) (at v 1) -- io.writeln io.stdout)
-> s.drain
;
Output:
0 -> -1
1 -> -0.9
2 -> -0.8
3 -> -0.7
4 -> -0.6
5 -> -0.5
6 -> -0.4
7 -> -0.3
8 -> -0.2
9 -> -0.1

Wren

Library: Wren-fmt
import "./fmt" for Fmt

var mapRange = Fn.new { |a, b, s| b.from + (s - a.from) * (b.to - b.from) / (a.to - a.from) }

var a = 0..10
var b = -1..0
for (s in a) {
    var t = mapRange.call(a, b, s)
    Fmt.print("$2d maps to $ h", s, t) 
}
Output:
 0 maps to -1
 1 maps to -0.9
 2 maps to -0.8
 3 maps to -0.7
 4 maps to -0.6
 5 maps to -0.5
 6 maps to -0.4
 7 maps to -0.3
 8 maps to -0.2
 9 maps to -0.1
10 maps to  0

XPL0

include c:\cxpl\codes;

func real Map(A1, A2, B1, B2, S);
real A1, A2, B1, B2, S;
return B1 + (S-A1)*(B2-B1)/(A2-A1);

int I;
[for I:= 0 to 10 do
    [if I<10 then ChOut(0, ^ );  IntOut(0, I);
    RlOut(0, Map(0., 10., -1., 0., float(I)));
    CrLf(0);
    ];
]
Output:
 0   -1.00000
 1   -0.90000
 2   -0.80000
 3   -0.70000
 4   -0.60000
 5   -0.50000
 6   -0.40000
 7   -0.30000
 8   -0.20000
 9   -0.10000
10    0.00000

Yabasic

sub MapRange(s, a1, a2, b1, b2)
    return b1+(s-a1)*(b2-b1)/(a2-a1)
end sub
 
for i = 0 to 10 step 2
    print i, " : ", MapRange(i,0,10,-1,0)
next

zkl

fcn mapRange([(a1,a2)], [(b1,b2)], s) // a1a2 is List(a1,a2)
   { b1 + ((s - a1) * (b2 - b1) / (a2 - a1)) }

r1:=T(0.0, 10.0); r2:=T(-1.0, 0.0);
foreach s in ([0.0 .. 10]){
   "%2d maps to %5.2f".fmt(s,mapRange(r1,r2, s)).println();
}
Output:
 0 maps to -1.00
 1 maps to -0.90
 2 maps to -0.80
 3 maps to -0.70
 4 maps to -0.60
 5 maps to -0.50
 6 maps to -0.40
 7 maps to -0.30
 8 maps to -0.20
 9 maps to -0.10
10 maps to  0.00