Price fraction: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added solution for Action!)
Line 64: Line 64:
0.90 0.94
0.90 0.94
1.00 1.00
1.00 1.00
</pre>

=={{header|Action!}}==
<lang Action!>DEFINE COUNT="20"
BYTE ARRAY levels=[6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 86 91 96 101]
BYTE ARRAY values=[10 18 26 32 38 44 50 54 58 62 66 70 74 78 82 86 90 94 98 100]

PROC PrintValue(BYTE v)
PrintB(v/100) Put('.)
v=v MOD 100
PrintB(v/10)
v=v MOD 10
PrintB(v)
RETURN

BYTE FUNC Map(BYTE v)
BYTE i

FOR i=0 TO COUNT-1
DO
IF v<levels(i) THEN
RETURN (values(i))
FI
OD
RETURN (v)

PROC Main()
BYTE i,v

FOR i=0 TO 100
DO
v=Map(i)
PrintValue(v)
IF i MOD 5=4 THEN
PutE()
ELSE
Put(' )
FI
OD
RETURN</lang>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Price_fraction.png Screenshot from Atari 8-bit computer]
<pre>
0.10 0.10 0.10 0.10 0.10
0.10 0.18 0.18 0.18 0.18
0.18 0.26 0.26 0.26 0.26
0.26 0.32 0.32 0.32 0.32
0.32 0.38 0.38 0.38 0.38
0.38 0.44 0.44 0.44 0.44
0.44 0.50 0.50 0.50 0.50
0.50 0.54 0.54 0.54 0.54
0.54 0.58 0.58 0.58 0.58
0.58 0.62 0.62 0.62 0.62
0.62 0.66 0.66 0.66 0.66
0.66 0.70 0.70 0.70 0.70
0.70 0.74 0.74 0.74 0.74
0.74 0.78 0.78 0.78 0.78
0.78 0.82 0.82 0.82 0.82
0.82 0.86 0.86 0.86 0.86
0.86 0.90 0.90 0.90 0.90
0.90 0.94 0.94 0.94 0.94
0.94 0.98 0.98 0.98 0.98
0.98 1.00 1.00 1.00 1.00
1.00
</pre>
</pre>



Revision as of 18:23, 30 November 2021

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

A friend of mine runs a pharmacy.   He has a specialized function in his Dispensary application which receives a decimal value of currency and replaces it to a standard value.   This value is regulated by a government department.


Task

Given a floating point value between   0.00   and   1.00,   rescale according to the following table:

>=  0.00  <  0.06  :=  0.10
>=  0.06  <  0.11  :=  0.18
>=  0.11  <  0.16  :=  0.26
>=  0.16  <  0.21  :=  0.32
>=  0.21  <  0.26  :=  0.38
>=  0.26  <  0.31  :=  0.44
>=  0.31  <  0.36  :=  0.50
>=  0.36  <  0.41  :=  0.54
>=  0.41  <  0.46  :=  0.58
>=  0.46  <  0.51  :=  0.62
>=  0.51  <  0.56  :=  0.66
>=  0.56  <  0.61  :=  0.70
>=  0.61  <  0.66  :=  0.74
>=  0.66  <  0.71  :=  0.78
>=  0.71  <  0.76  :=  0.82
>=  0.76  <  0.81  :=  0.86
>=  0.81  <  0.86  :=  0.90
>=  0.86  <  0.91  :=  0.94
>=  0.91  <  0.96  :=  0.98
>=  0.96  <  1.01  :=  1.00



11l

Translation of: Python

<lang 11l>F bisect_right(a, x)

  V lo = 0
  V hi = a.len
  L lo < hi
     V mid = (lo + hi) I/ 2
     I x < a[mid]
        hi = mid
     E
        lo = mid + 1
  R lo

V _cin = [0.06, 0.11, 0.16, 0.21, 0.26, 0.31, 0.36, 0.41, 0.46, 0.51, 0.56, 0.61, 0.66, 0.71, 0.76, 0.81, 0.86, 0.91, 0.96, 1.01] V _cout = [0.10, 0.18, 0.26, 0.32, 0.38, 0.44, 0.50, 0.54, 0.58, 0.62, 0.66, 0.70, 0.74, 0.78, 0.82, 0.86, 0.90, 0.94, 0.98, 1.00] F pricerounder(pricein)

  R :_cout[bisect_right(:_cin, pricein)]

L(i) 0..10

  print(‘#.2 #.2’.format(i / 10, pricerounder(i / 10)))</lang>
Output:
0.00 0.10
0.10 0.18
0.20 0.32
0.30 0.44
0.40 0.54
0.50 0.62
0.60 0.70
0.70 0.78
0.80 0.86
0.90 0.94
1.00 1.00

Action!

<lang Action!>DEFINE COUNT="20" BYTE ARRAY levels=[6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 86 91 96 101] BYTE ARRAY values=[10 18 26 32 38 44 50 54 58 62 66 70 74 78 82 86 90 94 98 100]

PROC PrintValue(BYTE v)

 PrintB(v/100) Put('.)
 v=v MOD 100
 PrintB(v/10)
 v=v MOD 10
 PrintB(v)

RETURN

BYTE FUNC Map(BYTE v)

 BYTE i
 FOR i=0 TO COUNT-1
 DO
   IF v<levels(i) THEN
     RETURN (values(i))
   FI
 OD

RETURN (v)

PROC Main()

 BYTE i,v
 FOR i=0 TO 100
 DO
   v=Map(i)
   PrintValue(v)
   IF i MOD 5=4 THEN
     PutE()
   ELSE
     Put(' )
   FI
 OD

RETURN</lang>

Output:

Screenshot from Atari 8-bit computer

0.10 0.10 0.10 0.10 0.10
0.10 0.18 0.18 0.18 0.18
0.18 0.26 0.26 0.26 0.26
0.26 0.32 0.32 0.32 0.32
0.32 0.38 0.38 0.38 0.38
0.38 0.44 0.44 0.44 0.44
0.44 0.50 0.50 0.50 0.50
0.50 0.54 0.54 0.54 0.54
0.54 0.58 0.58 0.58 0.58
0.58 0.62 0.62 0.62 0.62
0.62 0.66 0.66 0.66 0.66
0.66 0.70 0.70 0.70 0.70
0.70 0.74 0.74 0.74 0.74
0.74 0.78 0.78 0.78 0.78
0.78 0.82 0.82 0.82 0.82
0.82 0.86 0.86 0.86 0.86
0.86 0.90 0.90 0.90 0.90
0.90 0.94 0.94 0.94 0.94
0.94 0.98 0.98 0.98 0.98
0.98 1.00 1.00 1.00 1.00
1.00

Ada

<lang Ada> type Price is delta 0.01 digits 3 range 0.0..1.0; function Scale (Value : Price) return Price is

  X : constant array (1..19) of Price :=
         (  0.06, 0.11, 0.16, 0.21, 0.26,  0.31, 0.36, 0.41, 0.46, 0.51,
            0.56, 0.61, 0.66, 0.71, 0.76,  0.81, 0.86, 0.91, 0.96
         );
  Y : constant array (1..20) of Price :=
         (  0.10, 0.18, 0.26, 0.32, 0.38,  0.44, 0.50, 0.54, 0.58, 0.62,
            0.66, 0.70, 0.74, 0.78, 0.82,  0.86, 0.90, 0.94, 0.98, 1.0
         );
  Low    : Natural := X'First;
  High   : Natural := X'Last;
  Middle : Natural;

begin

  loop
     Middle := (Low + High) / 2;
     if Value = X (Middle) then
        return Y (Middle + 1);
     elsif Value < X (Middle) then
        if Low = Middle then
           return Y (Low);
        end if;
        High := Middle - 1;
     else
        if High = Middle then
           return Y (High + 1);
        end if;
        Low := Middle + 1;
     end if;
  end loop;

end Scale; </lang> The solution uses fixed point type to prevent rounding and representation issues. With the above declarations a full coverage test: <lang Ada> with Ada.Text_IO; use Ada.Text_IO; procedure Test_Price_Fraction is

  -- Put the declarations here
  Value : Price := Price'First;

begin

  loop
     Put_Line (Price'Image (Value) & "->" & Price'Image (Scale (Value)));
     exit when Value = Price'Last;
     Value := Price'Succ (Value);
  end loop;

end Test_Price_Fraction; </lang>

Output:
 0.00-> 0.10
 0.01-> 0.10
 0.02-> 0.10
 0.03-> 0.10
 0.04-> 0.10
 0.05-> 0.10
 0.06-> 0.18
 0.07-> 0.18
 0.08-> 0.18
 0.09-> 0.18
 0.10-> 0.18
 0.11-> 0.26
 0.12-> 0.26
 0.13-> 0.26
 0.14-> 0.26
 0.15-> 0.26
 0.16-> 0.32
 0.17-> 0.32
 0.18-> 0.32
 0.19-> 0.32
 0.20-> 0.32
 0.21-> 0.38
 0.22-> 0.38
 0.23-> 0.38
 0.24-> 0.38
 0.25-> 0.38
 0.26-> 0.44
 0.27-> 0.44
 0.28-> 0.44
 0.29-> 0.44
 0.30-> 0.44
 0.31-> 0.50
 0.32-> 0.50
 0.33-> 0.50
 0.34-> 0.50
 0.35-> 0.50
 0.36-> 0.54
 0.37-> 0.54
 0.38-> 0.54
 0.39-> 0.54
 0.40-> 0.54
 0.41-> 0.58
 0.42-> 0.58
 0.43-> 0.58
 0.44-> 0.58
 0.45-> 0.58
 0.46-> 0.62
 0.47-> 0.62
 0.48-> 0.62
 0.49-> 0.62
 0.50-> 0.62
 0.51-> 0.66
 0.52-> 0.66
 0.53-> 0.66
 0.54-> 0.66
 0.55-> 0.66
 0.56-> 0.70
 0.57-> 0.70
 0.58-> 0.70
 0.59-> 0.70
 0.60-> 0.70
 0.61-> 0.74
 0.62-> 0.74
 0.63-> 0.74
 0.64-> 0.74
 0.65-> 0.74
 0.66-> 0.78
 0.67-> 0.78
 0.68-> 0.78
 0.69-> 0.78
 0.70-> 0.78
 0.71-> 0.82
 0.72-> 0.82
 0.73-> 0.82
 0.74-> 0.82
 0.75-> 0.82
 0.76-> 0.86
 0.77-> 0.86
 0.78-> 0.86
 0.79-> 0.86
 0.80-> 0.86
 0.81-> 0.90
 0.82-> 0.90
 0.83-> 0.90
 0.84-> 0.90
 0.85-> 0.90
 0.86-> 0.94
 0.87-> 0.94
 0.88-> 0.94
 0.89-> 0.94
 0.90-> 0.94
 0.91-> 0.98
 0.92-> 0.98
 0.93-> 0.98
 0.94-> 0.98
 0.95-> 0.98
 0.96-> 1.00
 0.97-> 1.00
 0.98-> 1.00
 0.99-> 1.00
 1.00-> 1.00

ALGOL 68

Translation of: C

- note: This specimen retains the original C coding style.

Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny

<lang algol68>main: (

   # Just get a random price between 0 and 1 #
   # srand(time(NIL)); #
   REAL price := random;
   REAL tops := 0.06;
   REAL std val := 0.10;
   # Conditionals are a little odd here "(price-0.001 < tops AND
   price+0.001 > tops)" is to check if they are equal. Stupid
   C floats, right?   :) #
   WHILE ( price>tops OR (price-0.001 < tops AND price+0.001 > tops) ) AND tops<=1.01
   DO
       tops+:=0.05;
       IF std val < 0.26 THEN
               std val +:= 0.08
       ELIF std val < 0.50 THEN
               std val +:= 0.06
       ELSE
               std val +:= 0.04
       FI;
       IF std val > 0.98 THEN
               std val := 1.0
       FI
   OD;
   printf(($"Value :   "z.2dl,"Converted to standard :   "z.2dl$, price, std val))

)</lang>

Output:
Value :   0.38
Converted to standard :   0.54

AppleScript

Procedural

The task description doesn't make a lot of sense, implying that the pharmacist charges no more than 1.00 for his wares and that even whole-number prices are nudged by 0.10 and odd ones aren't. This offering takes any decimal currency value and standardises just the fractional part:

<lang applescript>-- This handler just returns the standardised real value. It's up to external processes to format it for display.

on standardisePrice(input)

   set integerPart to input div 1.0
   set fractionalPart to input mod 1.0
   
   if (fractionalPart is 0.0) then
       return input as real
   else if (fractionalPart < 0.06) then
       return integerPart + 0.1
   else if (fractionalPart < 0.16) then
       return integerPart + 0.18 + (fractionalPart - 0.06) div 0.05 * 0.08
   else if (fractionalPart < 0.36) then
       return integerPart + 0.32 + (fractionalPart - 0.16) div 0.05 * 0.06
   else if (fractionalPart < 0.96) then
       return integerPart + 0.54 + (fractionalPart - 0.36) div 0.05 * 0.04
   else
       return integerPart + 1.0
   end if

end standardisePrice

-- Test code: set originals to {} set standardised to {} repeat 20 times

   set price to (random number 100) / 100
   set end of originals to text 2 thru -2 of ((price + 10.001) as text)
   set end of standardised to text 2 thru -2 of ((standardisePrice(price) + 10.001) as text)

end repeat

set astid to AppleScript's text item delimiters set AppleScript's text item delimiters to ", " set output to linefeed & "Originals: " & originals & linefeed & "Standardised: " & standardised set AppleScript's text item delimiters to astid return output</lang>

Output:

<lang applescript>" Originals: 0.49, 0.79, 1.00, 0.83, 0.99, 0.23, 0.12, 0.28, 0.72, 0.37, 0.95, 0.51, 0.43, 0.52, 0.84, 0.89, 0.48, 0.48, 0.30, 0.01 Standardised: 0.62, 0.86, 1.00, 0.90, 1.00, 0.38, 0.26, 0.44, 0.82, 0.54, 0.98, 0.66, 0.58, 0.66, 0.90, 0.94, 0.62, 0.62, 0.44, 0.10"</lang>

An alternative that would save editing the handler in the event of the government department changing its directive would be to feed it a conversion table of up-to and standardised prices stored elsewhere.

<lang applescript>-- This handler just returns the standardised real value. It's up to external processes to format it for display.

on standardisePrice(input, table)

   set integerPart to input div 1.0
   set fractionalPart to input mod 1.0
   
   if (fractionalPart is 0.0) then return input as real
   repeat with thisEntry in table
       if (fractionalPart ≤ beginning of thisEntry) then return integerPart + (end of thisEntry)
   end repeat

end standardisePrice

-- Test code: -- The conceit here is that the conversion table has been obtained from a file or from a spreadsheet application. set table to {{0.05, 0.1}, {0.1, 0.18}, {0.15, 0.26}, {0.2, 0.32}, {0.25, 0.38}, {0.3, 0.44}, {0.35, 0.5}, {0.4, 0.54}, {0.45, 58}, {0.5, 0.62}, {0.55, 0.66}, {0.6, 0.7}, {0.65, 0.74}, {0.7, 0.78}, {0.75, 0.82}, {0.8, 0.86}, {0.85, 0.9}, {0.9, 0.94}, {0.95, 0.98}, {0.99, 1.0}}

set originals to {} set standardised to {} repeat 20 times

   set price to (random number 100) / 100
   set end of originals to text 2 thru -2 of ((price + 10.001) as text)
   set end of standardised to text 2 thru -2 of ((standardisePrice(price, table) + 10.001) as text)

end repeat

set astid to AppleScript's text item delimiters set AppleScript's text item delimiters to ", " set output to linefeed & "Originals: " & originals & linefeed & "Standardised: " & standardised set AppleScript's text item delimiters to astid return output</lang>

Output:

<lang applescript>" Originals: 0.92, 0.86, 0.10, 0.40, 0.00, 0.34, 0.44, 0.77, 0.67, 0.19, 1.00, 0.02, 0.49, 0.40, 0.61, 0.91, 0.85, 0.54, 0.01, 0.04 Standardised: 0.98, 0.94, 0.18, 0.54, 0.00, 0.50, 8.00, 0.86, 0.78, 0.32, 1.00, 0.10, 0.62, 0.54, 0.74, 0.98, 0.90, 0.66, 0.10, 0.10"</lang>

Functional

<lang applescript>---------------------- PRICE FRACTION ----------------------

property table : [¬

   {0.06, 0.1}, {0.11, 0.18}, {0.16, 0.26}, {0.21, 0.32}, {0.26, 0.38}, ¬
   {0.31, 0.44}, {0.36, 0.5}, {0.41, 0.54}, {0.46, 0.58}, {0.51, 0.62}, ¬
   {0.56, 0.66}, {0.61, 0.7}, {0.66, 0.74}, {0.71, 0.78}, {0.76, 0.82}, ¬
   {0.81, 0.86}, {0.86, 0.9}, {0.91, 0.94}, {0.96, 0.98}, {1.01, 1.0}]


-- rescaled :: [(Float, Float)] -> Float -> Float on rescaled(table)

   script
       on |λ|(x)
           if 0 > x or 1.01 < x then
               |Left|("Out of range.")
           else
               |Right|(snd(my head(dropWhile(compose(ge(x), my fst), table))))
           end if
       end |λ|
   end script

end rescaled



TEST ---------------------------

on run

   fTable("Price adjustments:\n", ¬
       showReal(2), either(identity, showReal(2)), ¬
       rescaled(table), enumFromThenTo(-0.05, 0, 1.1))

end run



GENERAL AND REUSABLE PURE FUNCTIONS ------------

-- Left :: a -> Either a b on |Left|(x)

   {type:"Either", |Left|:x, |Right|:missing value}

end |Left|


-- Right :: b -> Either a b on |Right|(x)

   {type:"Either", |Left|:missing value, |Right|:x}

end |Right|


-- compose (<<<) :: (b -> c) -> (a -> b) -> a -> c on compose(f, g)

   script
       property mf : mReturn(f)
       property mg : mReturn(g)
       on |λ|(x)
           mf's |λ|(mg's |λ|(x))
       end |λ|
   end script

end compose


-- drop :: Int -> [a] -> [a] -- drop :: Int -> String -> String on drop(n, xs)

   set c to class of xs
   if script is not c then
       if string is not c then
           if n < length of xs then
               items (1 + n) thru -1 of xs
           else
               {}
           end if
       else
           if n < length of xs then
               text (1 + n) thru -1 of xs
           else
               ""
           end if
       end if
   else
       take(n, xs) -- consumed
       return xs
   end if

end drop


-- dropWhile :: (a -> Bool) -> [a] -> [a] -- dropWhile :: (Char -> Bool) -> String -> String on dropWhile(p, xs)

   set lng to length of xs
   set i to 1
   tell mReturn(p)
       repeat while i ≤ lng and |λ|(item i of xs)
           set i to i + 1
       end repeat
   end tell
   drop(i - 1, xs)

end dropWhile


-- either :: (a -> c) -> (b -> c) -> Either a b -> c on either(lf, rf)

   script
       on |λ|(e)
           if missing value is |Left| of e then
               tell mReturn(rf) to |λ|(|Right| of e)
           else
               tell mReturn(lf) to |λ|(|Left| of e)
           end if
       end |λ|
   end script

end either


-- enumFromThenTo :: Int -> Int -> Int -> [Int] on enumFromThenTo(x1, x2, y)

   set xs to {}
   set d to x2 - x1
   set v to x1
   repeat until v ≥ y
       set end of xs to v
       set v to d + v
   end repeat
   return xs

end enumFromThenTo


-- foldl :: (a -> b -> a) -> a -> [b] -> a on foldl(f, startValue, xs)

   tell mReturn(f)
       set v to startValue
       set lng to length of xs
       repeat with i from 1 to lng
           set v to |λ|(v, item i of xs, i, xs)
       end repeat
       return v
   end tell

end foldl


-- fst :: (a, b) -> a on fst(tpl)

   if class of tpl is record then
       |1| of tpl
   else
       item 1 of tpl
   end if

end fst


-- fTable :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> String on fTable(s, xShow, fxShow, f, xs)

   set ys to map(xShow, xs)
   set w to maximum(map(my |length|, ys))
   script arrowed
       on |λ|(a, b)
           justifyRight(w, space, a) & " -> " & b
       end |λ|
   end script
   s & linefeed & unlines(zipWith(arrowed, ¬
       ys, map(compose(fxShow, f), xs)))

end fTable


-- ge :: Ord a => a -> a -> Bool on ge(a)

   -- True if a is greater
   -- than or equal to b.
   script
       on |λ|(b)
           a ≥ b
       end |λ|
   end script

end ge


-- head :: [a] -> a on head(xs)

   if xs = {} then
       missing value
   else
       item 1 of xs
   end if

end head


-- identity :: a -> a on identity(x)

   -- The argument unchanged.
   x

end identity


-- 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|


-- map :: (a -> b) -> [a] -> [b] on map(f, xs)

   -- The list obtained by applying f
   -- to each element of 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


-- max :: Ord a => a -> a -> a on max(x, y)

   if x > y then
       x
   else
       y
   end if

end max


-- maximum :: Ord a => [a] -> a on maximum(xs)

   script
       on |λ|(a, b)
           if a is missing value or b > a then
               b
           else
               a
           end if
       end |λ|
   end script
   
   foldl(result, missing value, xs)

end maximum


-- min :: Ord a => a -> a -> a on min(x, y)

   if y < x then
       y
   else
       x
   end if

end min


-- mReturn :: First-class m => (a -> b) -> m (a -> b) on mReturn(f)

   -- 2nd class handler function lifted into 1st class script wrapper. 
   if script is class of f then
       f
   else
       script
           property |λ| : f
       end script
   end if

end mReturn


-- 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 1 > n then return out
   set dbl to {a}
   
   repeat while (1 < n)
       if 0 < (n mod 2) then set out to out & dbl
       set n to (n div 2)
       set dbl to (dbl & dbl)
   end repeat
   return out & dbl

end replicate


-- showReal :: Num b => Int -> b -> String on showReal(n)

   script
       on |λ|(x)
           set {l, r} to splitOn(".", (x as real) as string)
           l & "." & justifyLeft(n, "0", r)
       end |λ|
   end script

end showReal


-- snd :: (a, b) -> b on snd(tpl)

   if class of tpl is record then
       |2| of tpl
   else
       item 2 of tpl
   end if

end snd


-- 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


-- str :: a -> String on str(x)

   x as text

end str


-- 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 |λ|() of xs
           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)

   -- A single string formed by the intercalation
   -- of a list of strings with the newline character.
   set {dlm, my text item delimiters} to ¬
       {my text item delimiters, linefeed}
   set s to xs as text
   set my text item delimiters to dlm
   s

end unlines


-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] on zipWith(f, xs, ys)

   set lng to min(length of xs, length of ys)
   set lst to {}
   if 1 > lng then
       return {}
   else
       tell mReturn(f)
           repeat with i from 1 to lng
               set end of lst to |λ|(item i of xs, item i of ys)
           end repeat
           return lst
       end tell
   end if

end zipWith</lang>

Output:
Price adjustments:

-0.05 -> Out of range.
 0.00 -> 0.10
 0.05 -> 0.10
 0.10 -> 0.18
 0.15 -> 0.26
 0.20 -> 0.32
 0.25 -> 0.38
 0.30 -> 0.44
 0.35 -> 0.50
 0.40 -> 0.54
 0.45 -> 0.58
 0.50 -> 0.62
 0.55 -> 0.66
 0.60 -> 0.70
 0.65 -> 0.74
 0.70 -> 0.78
 0.75 -> 0.82
 0.80 -> 0.86
 0.85 -> 0.90
 0.90 -> 0.94
 0.95 -> 0.98
 1.00 -> 1.00
 1.05 -> Out of range.

Arturo

<lang rebol>pricePoints: [

   0.06 0.10       0.11 0.18       0.16 0.26       0.21 0.32
   0.26 0.38       0.31 0.44       0.36 0.50       0.41 0.54
   0.46 0.58       0.51 0.62       0.56 0.66       0.61 0.70
   0.66 0.74       0.71 0.78       0.76 0.82       0.81 0.86
   0.86 0.90       0.91 0.94       0.96 0.98       1.01 1.00

]

getPricePoint: function [price][

   loop pricePoints [limit,correct][
       if price < limit -> return correct
   ]

]

tests: [0.3793 0.4425 0.0746 0.6918 0.2993 0.5486 0.7849 0.9383 0.2292]

loop tests 'test [

   print [test "=>" getPricePoint test]

]</lang>

Output:
0.3793 => 0.54 
0.4425 => 0.58 
0.0746 => 0.18 
0.6918 => 0.78 
0.2993 => 0.44 
0.5486 => 0.66 
0.7849 => 0.86 
0.9383 => 0.98 
0.2292 => 0.38

AutoHotkey

<lang AutoHotkey>; Submitted by MasterFocus --- http://tiny.cc/iTunis

Loop {

 InputBox, OutputVar, Price Fraction Example, Insert the value to be rounded.`n* [ 0 < value < 1 ]`n* Press ESC or Cancel to exit, , 200, 150
 If ErrorLevel
   Break
 MsgBox % "Input: " OutputVar "`nResult: " PriceFraction( OutputVar )

}

-----------------------------------------

PriceFraction( p_Input ) {

 If p_Input is not float ; returns 0 if input is not a float
   Return 0
 If ( ( p_Input <= 0 ) OR ( p_Input >= 1 ) ) ; returns 0 is input is out of range
   Return 0
 ; declaring the table (arbitrary delimiters in use are '§' and '|')
 l_List := "0.06|0.10§0.11|0.18§0.16|0.26§0.21|0.32§0.26|0.38§0.31|0.44§0.36|0.50§0.41|0.54§0.46|0.58§0.51|0.62§0.56|0.66§0.61|0.70§0.66|0.74§0.71|0.78§0.76|0.82§0.81|0.86§0.86|0.90§0.91|0.94§0.96|0.98§1.01|1.00"
 Loop, Parse, l_List, § ; retrieves each field (delimited by '§')
 {
   StringSplit, l_Array, A_LoopField, | ; splits current field (using delimiter '|')
   If ( p_Input <= l_Array1 )
     Return l_Array2 ; returns the second value if input <= first value
 }
 Return 0 ; returns 0, indicating failure (shouldn't be reached though)

}</lang>

AWK

<lang AWK> BEGIN {

   O = ".06 .11 .16 .21 .26 .31 .36 .41 .46 .51 .56 .61 .66 .71 .76 .81 .86 .91 .96 1.01"
   N = ".10 .18 .26 .32 .38 .44 .50 .54 .58 .62 .66 .70 .74 .78 .82 .86 .90 .94 .98 1.00"
   fields = split(O,Oarr," ") # original values
   split(N,Narr," ") # replacement values
   for (i=-.01; i<=1.02; i+=.01) { # test
     printf("%5.2f = %4.2f\n",i,lookup(i))
   }

} function lookup(n, i) {

   if (n < 0 || n > 1.01) {
     return(0) # when input is out of range
   }
   for (i=1; i<=fields; i++) {
     # +10 is used because .11 returned .18 instead of .26
     # under AWK95, GAWK, and MAWK; Thompson Automation's TAWK worked correctly
     if (n+10 < Oarr[i]+10) {
       return(Narr[i])
     }
   }

} </lang>

BASIC

Works with: QBasic

This could also be done by building an array, but I felt that this was simpler.

<lang qbasic>DECLARE FUNCTION PriceFraction! (price AS SINGLE)

RANDOMIZE TIMER DIM x AS SINGLE x = RND PRINT x, PriceFraction(x)

FUNCTION PriceFraction! (price AS SINGLE)

   'returns price unchanged if invalid value
   SELECT CASE price
       CASE IS < 0!
           PriceFraction! = price
       CASE IS < .06
           PriceFraction! = .1
       CASE IS < .11
           PriceFraction! = .18
       CASE IS < .16
           PriceFraction! = .26
       CASE IS < .21
           PriceFraction! = .32
       CASE IS < .26
           PriceFraction! = .38
       CASE IS < .31
           PriceFraction! = .44
       CASE IS < .36
           PriceFraction! = .5
       CASE IS < .41
           PriceFraction! = .54
       CASE IS < .46
           PriceFraction! = .58
       CASE IS < .51
           PriceFraction! = .62
       CASE IS < .56
           PriceFraction! = .66
       CASE IS < .61
           PriceFraction! = .7
       CASE IS < .66
           PriceFraction! = .74
       CASE IS < .71
           PriceFraction! = .78
       CASE IS < .76
           PriceFraction! = .82
       CASE IS < .81
           PriceFraction! = .86
       CASE IS < .86
           PriceFraction! = .9
       CASE IS < .91
           PriceFraction! = .94
       CASE IS < .96
           PriceFraction! = .98
       CASE IS < 1.01
           PriceFraction! = 1!
       CASE ELSE
           PriceFraction! = price
   END SELECT

END FUNCTION</lang>

Output:

(run 5 times)

.7388727      .82
.8593103      .9
.826687       .9
.3444635      .5
.0491907      .1

Commodore BASIC

We'll use a couple of arrays for translation. Should work for several other 8-bit BASICs after converting the screen control codes.

<lang gwbasic>1 rem price fraction 2 rem rosetta code 10 data 0.06,0.1,0.11,0.18,0.16,0.26,0.21,0.32,0.26,0.38,0.31,0.44,0.36,0.5 20 data 0.41,0.54,0.46,0.58,0.51,0.62,0.56,0.66,0.61,0.70,0.66,0.74,0.71,0.78 30 data 0.76,0.82,0.81,0.86,0.86,0.90,0.91,0.94,0.96,0.98,1.01,1.0 35 rem up=user price, th=threshold, pr=price, np=new price 40 dim th(20),pr(20):th(0)=0:pr(0)=0 45 for i=1 to 20:read th(i),pr(i):next 50 print chr$(147);chr$(14);"Price Fraction":print 60 print "What is the value to calculate (between 0.0 and 1.0)";:input up 65 if up<0 or up>1.0 then goto 60 70 gosub 500 80 print:print "You entered";up;chr$(157);", the new value is";np 90 print:print "Again (Y/N)? "; 95 get k$:if k$<>"y" and k$<>"n" then 95 100 print k$ 110 if k$="y" then goto 50 115 end 500 for i=0 to 20 510 if up<th(i) then np=pr(i):return 520 next i 530 np=1:return </lang>

Output:
Price Fraction

What is the value to calculate (between 0.0 and 1.0)? 0.83344

You entered .83344, the new value is .9

Again (Y/N)? Y
Price Fraction

What is the value to calculate (between 0.0 and 1.0)? 0.05889

You entered .05889, the new value is .1

Again (Y/N)? Y
Price Fraction

What is the value to calculate (between 0.0 and 1.0)? 0.36

You entered .36, the new value is .54

Again (Y/N)? N
ready.

BBC BASIC

<lang bbcbasic> PRINT FNpricefraction(0.5)

     END
     
     DEF FNpricefraction(p)
     IF p < 0.06 THEN = 0.10
     IF p < 0.11 THEN = 0.18
     IF p < 0.16 THEN = 0.26
     IF p < 0.21 THEN = 0.32
     IF p < 0.26 THEN = 0.38
     IF p < 0.31 THEN = 0.44
     IF p < 0.36 THEN = 0.50
     IF p < 0.41 THEN = 0.54
     IF p < 0.46 THEN = 0.58
     IF p < 0.51 THEN = 0.62
     IF p < 0.56 THEN = 0.66
     IF p < 0.61 THEN = 0.70
     IF p < 0.66 THEN = 0.74
     IF p < 0.71 THEN = 0.78
     IF p < 0.76 THEN = 0.82
     IF p < 0.81 THEN = 0.86
     IF p < 0.86 THEN = 0.90
     IF p < 0.91 THEN = 0.94
     IF p < 0.96 THEN = 0.98
     = 1.00</lang>

Beads

<lang Beads>beads 1 program 'Price fraction'

record a_table value rescaled

const table : array of a_table = [< value, rescaled 0.06, 0.10 0.11, 0.18 0.16, 0.26 0.21, 0.32 0.26, 0.38 0.31, 0.44 0.36, 0.50 0.41, 0.54 0.46, 0.58 0.51, 0.62 0.56, 0.66 0.61, 0.70 0.66, 0.74 0.71, 0.78 0.76, 0.82 0.81, 0.86 0.86, 0.90 0.91, 0.94 0.96, 0.98 1.01, 1.00 >]

const a_test = [0.05 0.62 0.34 0.93 0.45]

calc main_init loop across:a_test val:v loop across:table index:ix if v < table[ix].value log "{v} => {table[ix].rescaled}" exit</lang>

Output:
0.05 => 0.1
0.62 => 0.74
0.34 => 0.5
0.93 => 0.98
0.45 => 0.58


Bracmat

Bracmat has no native support for floating point variables nor for the fixed point values in the conversion table. Instead this solution just applies a string comparison. <lang bracmat>( ( convert

 =   
   .         ("0.06"."0.10")
             ("0.11"."0.18")
             ("0.16"."0.26")
             ("0.21"."0.32")
             ("0.26"."0.38")
             ("0.31"."0.44")
             ("0.36"."0.50")
             ("0.41"."0.54")
             ("0.46"."0.58")
             ("0.51"."0.62")
             ("0.56"."0.66")
             ("0.61"."0.70")
             ("0.66"."0.74")
             ("0.71"."0.78")
             ("0.76"."0.82")
             ("0.81"."0.86")
             ("0.86"."0.90")
             ("0.91"."0.94")
             ("0.96"."0.98")
             ("1.01"."1.00")
         : ? (>!arg.?arg) ?
       & !arg
     | "invalid input"
 )

& -1:?n & whl

 ' ( !n+1:?n:<103
   & ( @(!n:? [<2)&str$("0.0" !n):?a
     | @(!n:? [<3)&str$("0." !n):?a
     |   @(!n:?ones [-3 ?decimals)
       & str$(!ones "." !decimals):?a
     )
   & out$(!a "-->" convert$!a)
   )

)</lang>

Output:
0.00 --> 0.10
0.01 --> 0.10
0.02 --> 0.10
0.03 --> 0.10
0.04 --> 0.10
0.05 --> 0.10
0.06 --> 0.18
0.07 --> 0.18
0.08 --> 0.18
0.09 --> 0.18
0.10 --> 0.18
0.11 --> 0.26
0.12 --> 0.26
0.13 --> 0.26
0.14 --> 0.26
0.15 --> 0.26
0.16 --> 0.32
0.17 --> 0.32
  ...
0.85 --> 0.90
0.86 --> 0.94
0.87 --> 0.94
0.88 --> 0.94
0.89 --> 0.94
0.90 --> 0.94
0.91 --> 0.98
0.92 --> 0.98
0.93 --> 0.98
0.94 --> 0.98
0.95 --> 0.98
0.96 --> 1.00
0.97 --> 1.00
0.98 --> 1.00
0.99 --> 1.00
1.00 --> 1.00
1.01 --> invalid input
1.02 --> invalid input

C

<lang c>#include<stdio.h>

double table[][2] = { {0.06, 0.10}, {0.11, 0.18}, {0.16, 0.26}, {0.21, 0.32}, {0.26, 0.38}, {0.31, 0.44}, {0.36, 0.50}, {0.41, 0.54}, {0.46, 0.58}, {0.51, 0.62}, {0.56, 0.66}, {0.61, 0.70}, {0.66, 0.74}, {0.71, 0.78}, {0.76, 0.82}, {0.81, 0.86}, {0.86, 0.90}, {0.91, 0.94}, {0.96, 0.98}, {1.01, 1.00}, {-1, 0}, /* guarding element */ };

double price_fix(double x) { int i; for (i = 0; table[i][0] > 0; i++) if (x < table[i][0]) return table[i][1];

abort(); /* what else to do? */ }

int main() { int i; for (i = 0; i <= 100; i++) printf("%.2f %.2f\n", i / 100., price_fix(i / 100.));

return 0; }</lang>

C#

<lang csharp>namespace ConsoleApplication1 {

   class Program
   {
       static void Main(string[] args)
       {
           for (int x = 0; x < 10; x++)
           {
               Console.WriteLine("In: {0:0.00}, Out: {1:0.00}", ((double)x) / 10, SpecialRound(((double)x) / 10));
           }
           Console.WriteLine();
           for (int x = 0; x < 10; x++)
           {
               Console.WriteLine("In: {0:0.00}, Out: {1:0.00}", ((double)x) / 10 + 0.05, SpecialRound(((double)x) / 10 + 0.05));
           }
           Console.WriteLine();
           Console.WriteLine("In: {0:0.00}, Out: {1:0.00}", 1.01, SpecialRound(1.01));
           Console.Read();
       }
       private static double SpecialRound(double inValue)
       {
           if (inValue > 1) return 1;
           double[] Splitters = new double[] { 
                  0.00 , 0.06 , 0.11 , 0.16 , 0.21 , 
                  0.26 , 0.31 , 0.36 , 0.41 , 0.46 , 
                  0.51 , 0.56 , 0.61 , 0.66 , 0.71 , 
                  0.76 , 0.81 , 0.86 , 0.91 , 0.96 };
           double[] replacements = new double[] { 
                   0.10 , 0.18 , 0.26 , 0.32 , 0.38 ,
                   0.44 , 0.50 , 0.54 , 0.58 , 0.62 , 
                   0.66 , 0.70 , 0.74 , 0.78 , 0.82 , 
                   0.86 , 0.90 , 0.94 , 0.98 , 1.00 };
           for (int x = 0; x < Splitters.Length - 1; x++)
           {
               if (inValue >= Splitters[x] &&
                   inValue < Splitters[x + 1])
               {
                   return replacements[x];
               }
           }
           return inValue;
       }
   }

}</lang>

C++

<lang cpp>#include <iostream>

  1. include <cmath>

int main( ) {

  double froms[ ] = { 0.00 , 0.06 , 0.11 , 0.16 , 0.21 , 0.26 , 
      0.31 , 0.36 , 0.41 , 0.46 , 0.51 , 0.56 , 0.61 , 0.66 ,
      0.71 , 0.76 , 0.81 , 0.86 , 0.91 , 0.96 } ;
  double tos[ ] = { 0.06 , 0.11 , 0.16 , 0.21 , 0.26 , 0.31 ,
     0.36 , 0.41 , 0.46 , 0.51 , 0.56 , 0.61 , 0.66 , 0.71 ,
     0.76 , 0.81 , 0.86 , 0.91 , 0.96 , 1.01 } ;
  double replacements [] = { 0.10 , 0.18 , 0.26 , 0.32 , 0.38 ,
     0.44 , 0.50 , 0.54 , 0.58 , 0.62 , 0.66 , 0.70 , 0.74 ,
     0.78 , 0.82 , 0.86 , 0.90 , 0.94 , 0.98 , 1.00 } ;
  double number = 0.1 ;
  std::cout << "Enter a fractional number between 0 and 1 ( 0 to end )!\n" ;
  std::cin >> number ;
  while ( number != 0 ) {
     if ( number < 0 || number > 1 ) {

std::cerr << "Error! Only positive values between 0 and 1 are allowed!\n" ; return 1 ;

     }
     int n = 0 ;
     while ( ! ( number >= froms[ n ] && number < tos[ n ] ) ) 

n++ ;

     std::cout << "-->" << replacements[ n ] << '\n' ;
     std::cout << "Enter a fractional number ( 0 to end )!\n" ;
     std::cin >> number ;
  }
  return 0 ;

} </lang>

Output:
Enter a fractional number between 0 and 1 ( 0 to end )!
0.7
-->0.78
Enter a fractional number ( 0 to end )!
0.32
-->0.5
Enter a fractional number ( 0 to end )!
0.12
-->0.26
Enter a fractional number ( 0 to end )!
0

Clipper

<lang dbase>FUNCTION PriceFraction( npQuantDispensed )

   LOCAL aPriceFraction := { {0,.06,.1},;
                           {.06,.11,.18}, ;
                           {.11,.16,.26}, ;
                           {.16,.21,.32}, ;
                           {.21,.26,.38}, ;
                           {.26,.31,.44}, ;
                           {.31,.36,.5}, ;
                           {.36,.41,.54}, ;
                           {.41,.46,.58}, ;
                           {.46,.51,.62}, ;
                           {.51,.56,.66}, ;
                           {.56,.61,.7}, ;
                           {.61,.66,.74}, ;
                           {.66,.71,.78}, ;
                           {.71,.76,.82}, ;
                           {.76,.81,.86}, ;
                           {.81,.86,.9}, ;
                           {.86,.91,.94}, ;
                           {.91,.96,.98} }
   LOCAL nResult
   LOCAL nScan
   IF npQuantDispensed = 0
           nResult = 0
   ELSEIF npQuantDispensed >= .96
           nResult = 1
   ELSE
           nScan := ASCAN( aPriceFraction, ;
                  { |aItem| npQuantDispensed >= aItem[ 1 ] .AND.;
                            npQuantDispensed <  aItem[ 2 ] } )
           nResult := aPriceFraction[ nScan ][ 3 ]
   END IF
   RETURN nResult</lang>

The function above crashes with an array access bound error if the value passed is negative. Also, the spec. indicates that 0.00 should be replaced with standard value 0.10, not 0. The following is a more concise solution:

<lang Clipper>Procedure Main()

  Local i
  For i := -0.02 to 1.02 STEP 0.03
     ? i, "->", PriceFraction(i), i+0.02, "->", PriceFraction(i+0.02)
  Next

Return


Static Function PriceFraction( nValue )

  Local nResult
  Local n
  // Function is only defined for values 0 to 1.00
  // Return NIL for anything else
  // Table of values {V1, V2} = {Threshhold, Standard value}
  #define TV_THRESHHOLD 1
  #define TV_STD_VALUE  2
  Local aTable := { {0,    NIL },;
                    {0.06, 0.10},;
                    {0.11, 0.18},;
                    {0.16, 0.26},;
                    {0.21, 0.32},;
                    {0.26, 0.38},;
                    {0.31, 0.44},;
                    {0.36, 0.50},;
                    {0.41, 0.54},;
                    {0.46, 0.58},;
                    {0.51, 0.62},;
                    {0.56, 0.66},;
                    {0.61, 0.70},;
                    {0.66, 0.74},;
                    {0.71, 0.78},;
                    {0.76, 0.82},;
                    {0.81, 0.86},;
                    {0.86, 0.90},;
                    {0.91, 0.94},;
                    {0.96, 0.98},;
                    {1.01, 1.00} }
  n := AScan( aTable, {|x| nValue < x[TV_THRESHHOLD] })
  If n > 0
     nResult := aTable[n][TV_STD_VALUE]
  Else
     nResult := NIL
  Endif

Return nResult</lang>

Output:
        -0.02 -> NIL          0.00 ->          0.10
         0.01 ->          0.10          0.03 ->          0.10
         0.04 ->          0.10          0.06 ->          0.18
         0.07 ->          0.18          0.09 ->          0.18
         0.10 ->          0.18          0.12 ->          0.26
         0.13 ->          0.26          0.15 ->          0.26
         0.16 ->          0.32          0.18 ->          0.32
         0.19 ->          0.32          0.21 ->          0.38
         0.22 ->          0.38          0.24 ->          0.38
         0.25 ->          0.38          0.27 ->          0.44
         0.28 ->          0.44          0.30 ->          0.44
         0.31 ->          0.50          0.33 ->          0.50
         0.34 ->          0.50          0.36 ->          0.54
         0.37 ->          0.54          0.39 ->          0.54
         0.40 ->          0.54          0.42 ->          0.58
         0.43 ->          0.58          0.45 ->          0.58
         0.46 ->          0.62          0.48 ->          0.62
         0.49 ->          0.62          0.51 ->          0.66
         0.52 ->          0.66          0.54 ->          0.66
         0.55 ->          0.66          0.57 ->          0.70
         0.58 ->          0.70          0.60 ->          0.70
         0.61 ->          0.74          0.63 ->          0.74
         0.64 ->          0.74          0.66 ->          0.78
         0.67 ->          0.78          0.69 ->          0.78
         0.70 ->          0.78          0.72 ->          0.82
         0.73 ->          0.82          0.75 ->          0.82
         0.76 ->          0.86          0.78 ->          0.86
         0.79 ->          0.86          0.81 ->          0.90
         0.82 ->          0.90          0.84 ->          0.90
         0.85 ->          0.90          0.87 ->          0.94
         0.88 ->          0.94          0.90 ->          0.94
         0.91 ->          0.98          0.93 ->          0.98
         0.94 ->          0.98          0.96 ->          1.00
         0.97 ->          1.00          0.99 ->          1.00
         1.00 ->          1.00          1.02 -> NIL

Clojure

Translation of: JavaScript

<lang clojure>(def values [10 18 26 32 38 44 50 54 58 62 66 70 74 78 82 86 90 94 98 100])

(defn price [v]

 (format "%.2f" (double (/ (values (int (/ (- (* v 100) 1) 5))) 100))))</lang>



Output:
user=> (price 0.50)
"0.62"
user=> (let [k (map #(double (/ % 100)) (range 101))] (sort (zipmap k (map #(price %) k))))
([0.0 "0.10"] [0.01 "0.10"] [0.02 "0.10"] [0.03 "0.10"] [0.04 "0.10"] [0.05 "0.10"]
 [0.06 "0.18"] [0.07 "0.18"] [0.08 "0.18"] [0.09 "0.18"] [0.1 "0.18"] 
 [0.11 "0.26"] [0.12 "0.26"] [0.13 "0.26"] [0.14 "0.26"] [0.15 "0.26"] 
 [0.16 "0.32"] [0.17 "0.32"] [0.18 "0.32"] [0.19 "0.32"] [0.2 "0.32"] 
 [0.21 "0.38"] [0.22 "0.38"] [0.23 "0.38"] [0.24 "0.38"] [0.25 "0.38"]
 [0.26 "0.44"] [0.27 "0.44"] [0.28 "0.44"] [0.29 "0.44"] [0.3 "0.44"]
 [0.31 "0.50"] [0.32 "0.50"] [0.33 "0.50"] [0.34 "0.50"] [0.35 "0.50"] 
 [0.36 "0.54"] [0.37 "0.54"] [0.38 "0.54"] [0.39 "0.54"] [0.4 "0.54"] 
 [0.41 "0.58"] [0.42 "0.58"] [0.43 "0.58"] [0.44 "0.58"] [0.45 "0.58"] 
 [0.46 "0.62"] [0.47 "0.62"] [0.48 "0.62"] [0.49 "0.62"] [0.5 "0.62"] 
 [0.51 "0.66"] [0.52 "0.66"] [0.53 "0.66"] [0.54 "0.66"] [0.55 "0.66"] 
 [0.56 "0.70"] [0.57 "0.70"] [0.58 "0.70"] [0.59 "0.70"] [0.6 "0.70"] 
 [0.61 "0.74"] [0.62 "0.74"] [0.63 "0.74"] [0.64 "0.74"] [0.65 "0.74"] 
 [0.66 "0.78"] [0.67 "0.78"] [0.68 "0.78"] [0.69 "0.78"] [0.7 "0.78"] 
 [0.71 "0.82"] [0.72 "0.82"] [0.73 "0.82"] [0.74 "0.82"] [0.75 "0.82"] 
 [0.76 "0.86"] [0.77 "0.86"] [0.78 "0.86"] [0.79 "0.86"] [0.8 "0.86"] 
 [0.81 "0.90"] [0.82 "0.90"] [0.83 "0.90"] [0.84 "0.90"] [0.85 "0.90"] 
 [0.86 "0.94"] [0.87 "0.94"] [0.88 "0.94"] [0.89 "0.94"] [0.9 "0.94"] 
 [0.91 "0.98"] [0.92 "0.98"] [0.93 "0.98"] [0.94 "0.98"] [0.95 "0.98"] 
 [0.96 "1.00"] [0.97 "1.00"] [0.98 "1.00"] [0.99 "1.00"] [1.0 "1.00"])

Common Lisp

<lang lisp>(defun scale (value)

 (cond ((minusp value) (error "invalid value: ~A" value))
       ((< value 0.06) 0.10)
       ((< value 0.11) 0.18)
       ((< value 0.16) 0.26)
       ((< value 0.21) 0.32)
       ((< value 0.26) 0.38)
       ((< value 0.31) 0.44)
       ((< value 0.36) 0.50)
       ((< value 0.41) 0.54)
       ((< value 0.46) 0.58)
       ((< value 0.51) 0.62)
       ((< value 0.56) 0.66)
       ((< value 0.61) 0.70)
       ((< value 0.66) 0.74)
       ((< value 0.71) 0.78)
       ((< value 0.76) 0.82)
       ((< value 0.81) 0.86)
       ((< value 0.86) 0.90)
       ((< value 0.91) 0.94)
       ((< value 0.96) 0.98)
       ((< value 1.01) 1.00)
       (t (error "invalid value: ~A" value))))</lang>

D

<lang d>import std.stdio, std.range;

double priceRounder(in double price) pure nothrow in {

   assert(price >= 0 && price <= 1.0);

} body {

   static immutable cin  = [.06, .11, .16, .21, .26, .31, .36, .41,
                            .46, .51, .56, .61, .66, .71, .76, .81,
                            .86, .91, .96, 1.01],
                    cout = [.10, .18, .26, .32, .38, .44, .50, .54,
                            .58, .62, .66, .70, .74, .78, .82, .86,
                            .90, .94, .98, 1.00];
   return cout[cin.assumeSorted.lowerBound(price).length];

}

void main() {

   foreach (const price; [0.7388727, 0.8593103, 0.826687, 0.3444635])
       price.priceRounder.writeln;

}</lang>

Output:
0.82
0.9
0.9
0.5

Delphi

See Pascal.

Eiffel

<lang Eiffel> class APPLICATION

create make

feature

make --Tests the price_adjusted feature. local i: REAL do create price_fraction.initialize from i := 5 until i = 100 loop io.put_string ("Given: ") io.put_real (i / 100) io.put_string ("%TAdjusted:") io.put_real (price_fraction.adjusted_price (i / 100)) io.new_line i := i + 5 end end

price_fraction: PRICE_FRACTION

end </lang> <lang Eiffel> class PRICE_FRACTION

create initialize

feature

initialize -- Initializes limit and price to the given values. do limit := <<0.06, 0.11, 0.16, 0.21, 0.26, 0.31, 0.36, 0.41, 0.46, 0.51, 0.56, 0.61, 0.66, 0.71, 0.76, 0.81, 0.86, 0.91, 0.96, 1.01>> price := <<0.10, 0.18, 0.26, 0.32, 0.38, 0.44, 0.50, 0.54, 0.58, 0.62, 0.66, 0.70, 0.74, 0.78, 0.81, 0.86, 0.90, 0.94, 0.98, 1.00>> end

adjusted_price (n: REAL): REAL -- Adjusted price according to the given price values. local i: INTEGER found: BOOLEAN do from i := 1 until i > limit.count or found loop if n <= limit [i] then Result := (price [i]) found := True end i := i + 1 end end

feature {NONE}

limit: ARRAY [REAL]

price: ARRAY [REAL]

end </lang>

Output:
Given: 0.05    Adjusted:0.1
Given: 0.1     Adjusted:0.18
Given: 0.15    Adjusted:0.26
Given: 0.2     Adjusted:0.32
Given: 0.25    Adjusted:0.38
Given: 0.3     Adjusted:0.44
Given: 0.35    Adjusted:0.5
Given: 0.4     Adjusted:0.54
Given: 0.45    Adjusted:0.58
Given: 0.5     Adjusted:0.62
Given: 0.55    Adjusted:0.66
Given: 0.6     Adjusted:0.7
Given: 0.65    Adjusted:0.74
Given: 0.7     Adjusted:0.78
Given: 0.75    Adjusted:0.81
Given: 0.8     Adjusted:0.86
Given: 0.85    Adjusted:0.9
Given: 0.9     Adjusted:0.94
Given: 0.95    Adjusted:0.98


Elixir

<lang elixir>defmodule Price do

 @table [ {0.06, 0.10}, {0.11, 0.18}, {0.16, 0.26}, {0.21, 0.32}, {0.26, 0.38},
          {0.31, 0.44}, {0.36, 0.50}, {0.41, 0.54}, {0.46, 0.58}, {0.51, 0.62},
          {0.56, 0.66}, {0.61, 0.70}, {0.66, 0.74}, {0.71, 0.78}, {0.76, 0.82},
          {0.81, 0.86}, {0.86, 0.90}, {0.91, 0.94}, {0.96, 0.98}, {1.01, 1.00} ]
 
 def fraction(value) when value in 0..1 do
   {_, standard_value} = Enum.find(@table, fn {upper_limit, _} -> value < upper_limit end)
   standard_value
 end

end

val = for i <- 0..100, do: i/100 Enum.each(val, fn x ->

 :io.format "~5.2f ->~5.2f~n", [x, Price.fraction(x)]

end)</lang>

Output:
 0.00 -> 0.10
 0.01 -> 0.10
 0.02 -> 0.10
 0.03 -> 0.10
 0.04 -> 0.10
 0.05 -> 0.10
 0.06 -> 0.18
 0.07 -> 0.18
 0.08 -> 0.18
 0.09 -> 0.18
 0.10 -> 0.18
 0.11 -> 0.26
...
 0.95 -> 0.98
 0.96 -> 1.00
 0.97 -> 1.00
 0.98 -> 1.00
 0.99 -> 1.00
 1.00 -> 1.00

Erlang

<lang erlang>priceFraction(N) when N < 0 orelse N > 1 ->

   erlang:error('Values must be between 0 and 1.');

priceFraction(N) when N < 0.06 -> 0.10; priceFraction(N) when N < 0.11 -> 0.18; priceFraction(N) when N < 0.16 -> 0.26; priceFraction(N) when N < 0.21 -> 0.32; priceFraction(N) when N < 0.26 -> 0.38; priceFraction(N) when N < 0.31 -> 0.44; priceFraction(N) when N < 0.36 -> 0.50; priceFraction(N) when N < 0.41 -> 0.54; priceFraction(N) when N < 0.46 -> 0.58; priceFraction(N) when N < 0.51 -> 0.62; priceFraction(N) when N < 0.56 -> 0.66; priceFraction(N) when N < 0.61 -> 0.70; priceFraction(N) when N < 0.66 -> 0.74; priceFraction(N) when N < 0.71 -> 0.78; priceFraction(N) when N < 0.76 -> 0.82; priceFraction(N) when N < 0.81 -> 0.86; priceFraction(N) when N < 0.86 -> 0.90; priceFraction(N) when N < 0.91 -> 0.94; priceFraction(N) when N < 0.96 -> 0.98; priceFraction(N) -> 1.00.</lang>

Euphoria

Translation of: C

<lang euphoria>constant table = {

   {0.06, 0.10}, {0.11, 0.18}, {0.16, 0.26}, {0.21, 0.32},
   {0.26, 0.38}, {0.31, 0.44}, {0.36, 0.50}, {0.41, 0.54},
   {0.46, 0.58}, {0.51, 0.62}, {0.56, 0.66}, {0.61, 0.70},
   {0.66, 0.74}, {0.71, 0.78}, {0.76, 0.82}, {0.81, 0.86},
   {0.86, 0.90}, {0.91, 0.94}, {0.96, 0.98}, {1.01, 1.00}

}

function price_fix(atom x)

   for i = 1 to length(table) do
       if x < table[i][1] then
           return table[i][2]
       end if
   end for
   return -1

end function

for i = 0 to 99 do

   printf(1, "%.2f %.2f\n", { i/100, price_fix(i/100) })

end for</lang>

F#

Inspired by Python's bisect solution. Using decimal (System.Decimal) to avoid number representation problems with floats. <lang fsharp>let cin = [ 0.06m .. 0.05m ..1.01m ] let cout = [0.1m; 0.18m] @ [0.26m .. 0.06m .. 0.44m] @ [0.50m .. 0.04m .. 0.98m] @ [1.m]

let priceadjuster p =

   let rec bisect lo hi = 
       if lo < hi then
           let mid = (lo+hi)/2.
           let left = p < cin.[int mid]
           bisect (if left then lo else mid+1.) (if left then mid else hi)
       else lo    
   if p < 0.m || 1.m < p then p
   else cout.[int (bisect 0. (float cin.Length))]

[ 0.m .. 0.01m .. 1.m ] |> Seq.ofList |> Seq.iter (fun p -> printfn "%.2f -> %.2f" p (priceadjuster p))</lang>

Output:

The same as shown by Ada as of 2013-11-03T17:42Z (apart from whitespace formatting)

Factor

<lang factor>CONSTANT: dispensary-data { { 0.06 0.10 } { 0.11 0.18 } { 0.16 0.26 } { 0.21 0.32 } { 0.26 0.38 } { 0.31 0.44 } { 0.36 0.50 } { 0.41 0.54 } { 0.46 0.58 } { 0.51 0.62 } { 0.56 0.66 } { 0.61 0.70 } { 0.66 0.74 } { 0.71 0.78 } { 0.76 0.82 } { 0.81 0.86 } { 0.86 0.90 } { 0.91 0.94 } { 0.96 0.98 } { 1.01 1.00 } }

price-fraction ( n -- n ) dispensary-data [ first over >= ] find 2nip second ;

{ 0 0.5 0.65 0.66 1 } [ price-fraction ] map</lang>

Output:

{ 0.1 0.62 0.74 0.74 1.0 }

Fantom

<lang fantom> class Defn // to hold the three numbers from a 'row' in the table {

 Float low
 Float high
 Float value
 new make (Float low, Float high, Float value)
 {
   this.low = low
   this.high = high
   this.value = value
 }

}

class PriceConverter {

 Defn[] defns := [,]
 new make (Str table) // process given table and store numbers from each row in a defn
 {
   table.split('\n').each |Str line|
   {
     data := line.split
     defns.add (Defn(Float.fromStr(data[1]), Float.fromStr(data[3]), Float.fromStr(data[5])))
   }
 }
 public Float convert (Float price) // convert by looking through list of defns
 {
   Float result := price
   defns.each |Defn defn|
   {
     if (price >= defn.low && price < defn.high) 
       result = defn.value
   }
   return result
 }

}

class Main {

 public static Void main ()
 {
   table := ">=  0.00  <  0.06  :=  0.10
             >=  0.06  <  0.11  :=  0.18
             >=  0.11  <  0.16  :=  0.26
             >=  0.16  <  0.21  :=  0.32
             >=  0.21  <  0.26  :=  0.38
             >=  0.26  <  0.31  :=  0.44
             >=  0.31  <  0.36  :=  0.50
             >=  0.36  <  0.41  :=  0.54
             >=  0.41  <  0.46  :=  0.58
             >=  0.46  <  0.51  :=  0.62
             >=  0.51  <  0.56  :=  0.66
             >=  0.56  <  0.61  :=  0.70
             >=  0.61  <  0.66  :=  0.74
             >=  0.66  <  0.71  :=  0.78
             >=  0.71  <  0.76  :=  0.82
             >=  0.76  <  0.81  :=  0.86
             >=  0.81  <  0.86  :=  0.90
             >=  0.86  <  0.91  :=  0.94
             >=  0.91  <  0.96  :=  0.98
             >=  0.96  <  1.01  :=  1.00"
   converter := PriceConverter (table)
   10.times  // simple test with random values
   { 
     price := (0..100).random.toFloat / 100
     echo ("$price -> ${converter.convert (price)}")
   }
 }

} </lang>

Forth

A floating-point version wouldn't be hard -- four words would change ( , @ @ cell+ -to- f, f@ f@ float+ ), EVALUATE would be replaced with a small word that forced a floating-point interpretation, and the return stack would not be used in ROUND -- but it would be strikingly unusual. See this page's discussion.

<lang forth>: as begin parse-word dup while evaluate , repeat 2drop ;

create bounds as 96 91 86 81 76 71 66 61 56 51 46 41 36 31 26 21 16 11 6 0 create official as 100 98 94 90 86 82 78 74 70 66 62 58 54 50 44 38 32 26 18 10

official@ ( a-bounds -- +n )
 \ (a+n) - a + b = (a+n) + (b - a) = (b+n)
 [ official bounds - ] literal + @ ;
round ( n-cents -- n-cents' )
 >r bounds begin dup @ r@ > while cell+ repeat
 r> drop official@ ;</lang>

Fortran

Works with: Fortran version 90 and later

<lang fortran>program price_fraction

 implicit none
 integer, parameter :: i_max = 10
 integer :: i
 real, dimension (20), parameter :: in =                           &
   & (/0.00, 0.06, 0.11, 0.16, 0.21, 0.26, 0.31, 0.36, 0.41, 0.46, &
   &   0.51, 0.56, 0.61, 0.66, 0.71, 0.76, 0.81, 0.86, 0.91, 0.96/)
 real, dimension (20), parameter :: out =                          &
   & (/0.10, 0.18, 0.26, 0.32, 0.38, 0.44, 0.50, 0.54, 0.58, 0.62, &
   &   0.66, 0.70, 0.74, 0.78, 0.82, 0.86, 0.90, 0.94, 0.98, 1.00/)
 real :: r
 do i = 1, i_max
   call random_number (r)
   write (*, '(f8.6, 1x, f4.2)') r, out (maxloc (in, r >= in))
 end do

end program price_fraction</lang>

Output:

<lang>0.997560 1.00 0.566825 0.70 0.965915 1.00 0.747928 0.82 0.367391 0.54 0.480637 0.62 0.073754 0.18 0.005355 0.10 0.347081 0.50 0.342244 0.50</lang>

FreeBASIC

<lang freebasic>' FB 1.050.0 Win64

Function rescale(price As Double) As Double

 If price < 0.00 OrElse price > 1.00 Then Return price
 Select Case price
   Case Is < 0.06 : Return 0.10
   Case Is < 0.11 : Return 0.18
   Case Is < 0.16 : Return 0.26
   Case Is < 0.21 : Return 0.32
   Case Is < 0.26 : Return 0.38
   Case Is < 0.31 : Return 0.44
   Case Is < 0.36 : Return 0.50
   Case Is < 0.41 : Return 0.54
   Case Is < 0.46 : Return 0.58
   Case Is < 0.51 : Return 0.62
   Case Is < 0.56 : Return 0.66
   Case Is < 0.61 : Return 0.70
   Case Is < 0.66 : Return 0.74
   Case Is < 0.71 : Return 0.78
   Case Is < 0.76 : Return 0.82
   Case Is < 0.81 : Return 0.86
   Case Is < 0.86 : Return 0.90
   Case Is < 0.91 : Return 0.94
   Case Is < 0.96 : Return 0.98
 End Select
 Return 1.00

End Function

For i As Integer = 1 To 100

 Dim d As Double = i/100.0
 Print Using "#.##"; d;
 Print " -> ";
 Print Using "#.##"; rescale(d);
 Print "  ";
 If i Mod 5 = 0 Then Print

Next

Print Print "Press any key to quit" Sleep</lang>

Output:
0.01 -> 0.10  0.02 -> 0.10  0.03 -> 0.10  0.04 -> 0.10  0.05 -> 0.10
0.06 -> 0.18  0.07 -> 0.18  0.08 -> 0.18  0.09 -> 0.18  0.10 -> 0.18
0.11 -> 0.26  0.12 -> 0.26  0.13 -> 0.26  0.14 -> 0.26  0.15 -> 0.26
0.16 -> 0.32  0.17 -> 0.32  0.18 -> 0.32  0.19 -> 0.32  0.20 -> 0.32
0.21 -> 0.38  0.22 -> 0.38  0.23 -> 0.38  0.24 -> 0.38  0.25 -> 0.38
0.26 -> 0.44  0.27 -> 0.44  0.28 -> 0.44  0.29 -> 0.44  0.30 -> 0.44
0.31 -> 0.50  0.32 -> 0.50  0.33 -> 0.50  0.34 -> 0.50  0.35 -> 0.50
0.36 -> 0.54  0.37 -> 0.54  0.38 -> 0.54  0.39 -> 0.54  0.40 -> 0.54
0.41 -> 0.58  0.42 -> 0.58  0.43 -> 0.58  0.44 -> 0.58  0.45 -> 0.58
0.46 -> 0.62  0.47 -> 0.62  0.48 -> 0.62  0.49 -> 0.62  0.50 -> 0.62
0.51 -> 0.66  0.52 -> 0.66  0.53 -> 0.66  0.54 -> 0.66  0.55 -> 0.66
0.56 -> 0.70  0.57 -> 0.70  0.58 -> 0.70  0.59 -> 0.70  0.60 -> 0.70
0.61 -> 0.74  0.62 -> 0.74  0.63 -> 0.74  0.64 -> 0.74  0.65 -> 0.74
0.66 -> 0.78  0.67 -> 0.78  0.68 -> 0.78  0.69 -> 0.78  0.70 -> 0.78
0.71 -> 0.82  0.72 -> 0.82  0.73 -> 0.82  0.74 -> 0.82  0.75 -> 0.82
0.76 -> 0.86  0.77 -> 0.86  0.78 -> 0.86  0.79 -> 0.86  0.80 -> 0.86
0.81 -> 0.90  0.82 -> 0.90  0.83 -> 0.90  0.84 -> 0.90  0.85 -> 0.90
0.86 -> 0.94  0.87 -> 0.94  0.88 -> 0.94  0.89 -> 0.94  0.90 -> 0.94
0.91 -> 0.98  0.92 -> 0.98  0.93 -> 0.98  0.94 -> 0.98  0.95 -> 0.98
0.96 -> 1.00  0.97 -> 1.00  0.98 -> 1.00  0.99 -> 1.00  1.00 -> 1.00

Gambas

Click this link to run this code <lang gambas>Public Sub Main() Dim byValue As Byte[] = [10, 18, 26, 32, 38, 44, 50, 54, 58, 62, 66, 70, 74, 78, 82, 86, 90, 94, 98, 100] Dim byLimit As Byte[] = [6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76, 81, 86, 91, 96] Dim byCount, byCheck As Byte

For byCount = 0 To 100

 For byCheck = 0 To byLimit.Max
   If byCount < byLimit[byCheck] Then Break
 Next
 Print Format(byCount / 100, "0.00") & " = " & Format(byValue[byCheck] / 100, "0.00") & gb.Tab;
 If byCount Mod 5 = 0 Then Print

Next

End </lang> Output:

0.00 = 0.10
0.01 = 0.10     0.02 = 0.10     0.03 = 0.10     0.04 = 0.10     0.05 = 0.10
0.06 = 0.18     0.07 = 0.18     0.08 = 0.18     0.09 = 0.18     0.10 = 0.18
0.11 = 0.26     0.12 = 0.26     0.13 = 0.26     0.14 = 0.26     0.15 = 0.26
0.16 = 0.32     0.17 = 0.32     0.18 = 0.32     0.19 = 0.32     0.20 = 0.32
0.21 = 0.38     0.22 = 0.38     0.23 = 0.38     0.24 = 0.38     0.25 = 0.38
0.26 = 0.44     0.27 = 0.44     0.28 = 0.44     0.29 = 0.44     0.30 = 0.44
0.31 = 0.50     0.32 = 0.50     0.33 = 0.50     0.34 = 0.50     0.35 = 0.50
0.36 = 0.54     0.37 = 0.54     0.38 = 0.54     0.39 = 0.54     0.40 = 0.54
0.41 = 0.58     0.42 = 0.58     0.43 = 0.58     0.44 = 0.58     0.45 = 0.58
0.46 = 0.62     0.47 = 0.62     0.48 = 0.62     0.49 = 0.62     0.50 = 0.62
0.51 = 0.66     0.52 = 0.66     0.53 = 0.66     0.54 = 0.66     0.55 = 0.66
0.56 = 0.70     0.57 = 0.70     0.58 = 0.70     0.59 = 0.70     0.60 = 0.70
0.61 = 0.74     0.62 = 0.74     0.63 = 0.74     0.64 = 0.74     0.65 = 0.74
0.66 = 0.78     0.67 = 0.78     0.68 = 0.78     0.69 = 0.78     0.70 = 0.78
0.71 = 0.82     0.72 = 0.82     0.73 = 0.82     0.74 = 0.82     0.75 = 0.82
0.76 = 0.86     0.77 = 0.86     0.78 = 0.86     0.79 = 0.86     0.80 = 0.86
0.81 = 0.90     0.82 = 0.90     0.83 = 0.90     0.84 = 0.90     0.85 = 0.90
0.86 = 0.94     0.87 = 0.94     0.88 = 0.94     0.89 = 0.94     0.90 = 0.94
0.91 = 0.98     0.92 = 0.98     0.93 = 0.98     0.94 = 0.98     0.95 = 0.98
0.96 = 1.00     0.97 = 1.00     0.98 = 1.00     0.99 = 1.00     1.00 = 1.00

Go

<lang go>package main

import "fmt"

func pf(v float64) float64 {

   switch {
   case v < .06:
       return .10
   case v < .11:
       return .18
   case v < .16:
       return .26
   case v < .21:
       return .32
   case v < .26:
       return .38
   case v < .31:
       return .44
   case v < .36:
       return .50
   case v < .41:
       return .54
   case v < .46:
       return .58
   case v < .51:
       return .62
   case v < .56:
       return .66
   case v < .61:
       return .70
   case v < .66:
       return .74
   case v < .71:
       return .78
   case v < .76:
       return .82
   case v < .81:
       return .86
   case v < .86:
       return .90
   case v < .91:
       return .94
   case v < .96:
       return .98
   }
   return 1

}

func main() {

   tests := []float64{0.3793, 0.4425, 0.0746, 0.6918, 0.2993,
       0.5486, 0.7848, 0.9383, 0.2292, 0.9760}
   for _, v := range tests {
       fmt.Printf("%0.4f -> %0.2f\n", v, pf(v))
   }

}</lang>

0.3793 -> 0.54
0.4425 -> 0.58
0.0746 -> 0.18
0.6918 -> 0.78
0.2993 -> 0.44
0.5486 -> 0.66
0.7848 -> 0.86
0.9383 -> 0.98
0.2292 -> 0.38
0.9760 -> 1.00

Groovy

<lang groovy>def priceFraction(value) {

   assert value >= 0.0 && value <= 1.0
   def priceMappings = [(0.06): 0.10, (0.11): 0.18, (0.16): 0.26, (0.21): 0.32, (0.26): 0.38,
        (0.31): 0.44, (0.36): 0.50, (0.41): 0.54, (0.46): 0.58, (0.51): 0.62,
        (0.56): 0.66, (0.61): 0.70, (0.66): 0.74, (0.71): 0.78, (0.76): 0.82,
        (0.81): 0.86, (0.86): 0.90, (0.91): 0.94, (0.96): 0.98]
   for (price in priceMappings.keySet()) {
       if (value < price) return priceMappings[price]
   }
   1.00

}

for (def v = 0.00; v <= 1.00; v += 0.01) {

   println "$v --> ${priceFraction(v)}"

}</lang>

Output:
0.00 --> 0.10
0.01 --> 0.10
0.02 --> 0.10
0.03 --> 0.10
0.04 --> 0.10
0.05 --> 0.10
0.06 --> 0.18
0.07 --> 0.18
0.08 --> 0.18
0.09 --> 0.18
0.10 --> 0.18
0.11 --> 0.26
0.12 --> 0.26
0.13 --> 0.26
0.14 --> 0.26
0.15 --> 0.26
0.16 --> 0.32
0.17 --> 0.32
0.18 --> 0.32
0.19 --> 0.32
0.20 --> 0.32
0.21 --> 0.38
0.22 --> 0.38
0.23 --> 0.38
0.24 --> 0.38
0.25 --> 0.38
0.26 --> 0.44
0.27 --> 0.44
0.28 --> 0.44
0.29 --> 0.44
0.30 --> 0.44
0.31 --> 0.50
0.32 --> 0.50
0.33 --> 0.50
0.34 --> 0.50
0.35 --> 0.50
0.36 --> 0.54
0.37 --> 0.54
0.38 --> 0.54
0.39 --> 0.54
0.40 --> 0.54
0.41 --> 0.58
0.42 --> 0.58
0.43 --> 0.58
0.44 --> 0.58
0.45 --> 0.58
0.46 --> 0.62
0.47 --> 0.62
0.48 --> 0.62
0.49 --> 0.62
0.50 --> 0.62
0.51 --> 0.66
0.52 --> 0.66
0.53 --> 0.66
0.54 --> 0.66
0.55 --> 0.66
0.56 --> 0.70
0.57 --> 0.70
0.58 --> 0.70
0.59 --> 0.70
0.60 --> 0.70
0.61 --> 0.74
0.62 --> 0.74
0.63 --> 0.74
0.64 --> 0.74
0.65 --> 0.74
0.66 --> 0.78
0.67 --> 0.78
0.68 --> 0.78
0.69 --> 0.78
0.70 --> 0.78
0.71 --> 0.82
0.72 --> 0.82
0.73 --> 0.82
0.74 --> 0.82
0.75 --> 0.82
0.76 --> 0.86
0.77 --> 0.86
0.78 --> 0.86
0.79 --> 0.86
0.80 --> 0.86
0.81 --> 0.90
0.82 --> 0.90
0.83 --> 0.90
0.84 --> 0.90
0.85 --> 0.90
0.86 --> 0.94
0.87 --> 0.94
0.88 --> 0.94
0.89 --> 0.94
0.90 --> 0.94
0.91 --> 0.98
0.92 --> 0.98
0.93 --> 0.98
0.94 --> 0.98
0.95 --> 0.98
0.96 --> 1.00
0.97 --> 1.00
0.98 --> 1.00
0.99 --> 1.00
1.00 --> 1.00

Haskell

<lang haskell>price_fraction n

 | n < 0 || n > 1 = error "Values must be between 0 and 1."
 | n < 0.06 = 0.10
 | n < 0.11 = 0.18
 | n < 0.16 = 0.26
 | n < 0.21 = 0.32
 | n < 0.26 = 0.38
 | n < 0.31 = 0.44
 | n < 0.36 = 0.50
 | n < 0.41 = 0.54
 | n < 0.46 = 0.58
 | n < 0.51 = 0.62
 | n < 0.56 = 0.66
 | n < 0.61 = 0.70
 | n < 0.66 = 0.74
 | n < 0.71 = 0.78
 | n < 0.76 = 0.82
 | n < 0.81 = 0.86
 | n < 0.86 = 0.90
 | n < 0.91 = 0.94
 | n < 0.96 = 0.98
 | otherwise = 1.00</lang>

Alternative

Translation of: OCaml

:

<lang haskell>table = [

   (0.06, 0.10),   (0.11, 0.18),   (0.16, 0.26),   (0.21, 0.32),   (0.26, 0.38),
   (0.31, 0.44),   (0.36, 0.50),   (0.41, 0.54),   (0.46, 0.58),   (0.51, 0.62),
   (0.56, 0.66),   (0.61, 0.70),   (0.66, 0.74),   (0.71, 0.78),   (0.76, 0.82),
   (0.81, 0.86),   (0.86, 0.90),   (0.91, 0.94),   (0.96, 0.98),   (1.01, 1.00),
 ]

price_fraction n

 | n < 0 || n > 1 = error "Values must be between 0 and 1."
 | otherwise = snd $ head $ dropWhile ((<= n) . fst) table</lang>

HicEst

<lang HicEst>DIMENSION upperbound(20), rescaleTo(20), temp(20) upperbound = (.06,.11,.16,.21,.26,.31,.36,.41,.46,.51,.56,.61,.66,.71,.76,.81,.86,.91,.96,1.01) rescaleTo = (.10,.18,.26,.32,.38,.44,.50,.54,.58,.62,.66,.70,.74,.78,.82,.86,.90,.94,.98,1.00)

DO test = 1, 10

 value = RAN(0.5, 0.5)
 temp = value > upperbound
 PriceFraction = rescaleTo( INDEX(temp, 0) )
 WRITE(Format="F8.6, F6.2") value, PriceFraction

ENDDO</lang>

0.589230  0.70
0.017623  0.10
0.314343  0.50
0.553303  0.66
0.676283  0.78
0.016883  0.10
0.265656  0.44
0.460880  0.62
0.837450  0.90
0.228953  0.38

Icon and Unicon

<lang Icon> record Bounds(low,high,new)

  1. rescale given value according to a list of bounds

procedure rescale (i, bounds)

 every bound := !bounds do 
   if bound.low <= i < bound.high
     then return bound.new
 return fail # could not find i in bounds

end

procedure main ()

 bounds := [
   Bounds(0.00, 0.06, 0.10),
   Bounds(0.06, 0.11, 0.18),
   Bounds(0.11, 0.16, 0.26),
   Bounds(0.16, 0.21, 0.32),
   Bounds(0.21, 0.26, 0.38),
   Bounds(0.26, 0.31, 0.44),
   Bounds(0.31, 0.36, 0.50),
   Bounds(0.36, 0.41, 0.54),
   Bounds(0.41, 0.46, 0.58),
   Bounds(0.46, 0.51, 0.62),
   Bounds(0.51, 0.56, 0.66),
   Bounds(0.56, 0.61, 0.70),
   Bounds(0.61, 0.66, 0.74),
   Bounds(0.66, 0.71, 0.78),
   Bounds(0.71, 0.76, 0.82),
   Bounds(0.76, 0.81, 0.86),
   Bounds(0.81, 0.86, 0.90),
   Bounds(0.86, 0.91, 0.94),
   Bounds(0.91, 0.96, 0.98),
   Bounds(0.96, 1.01, 1.00)
 ]
 # test the procedure
 every i := 0.00 to 1.00 by 0.1 do {
   write (i || " rescaled is " || rescale(i, bounds))
 }

end </lang>

Output:
0.0 rescaled is 0.1
0.1 rescaled is 0.18
0.2 rescaled is 0.32
0.3 rescaled is 0.44
0.4 rescaled is 0.54
0.5 rescaled is 0.62
0.6 rescaled is 0.7
0.7 rescaled is 0.78
0.8 rescaled is 0.86
0.9 rescaled is 0.94
1.0 rescaled is 1.0

Inform 7

Inform doesn't have native floating-point support; this version uses fixed point numbers with two decimal places.

<lang inform7>Home is a room.

Price is a kind of value. 0.99 specifies a price.

Table of Price Standardization upper bound replacement 0.06 0.10 0.11 0.18 0.16 0.26 0.21 0.32 0.26 0.38 0.31 0.44 0.36 0.50 0.41 0.54 0.46 0.58 0.51 0.62 0.56 0.66 0.61 0.70 0.66 0.74 0.71 0.78 0.76 0.82 0.81 0.86 0.86 0.90 0.91 0.94 0.96 0.98 1.01 1.00

To decide which price is the standardized value of (P - price): repeat with N running from 1 to the number of rows in the Table of Price Standardization: choose row N in the Table of Price Standardization; if P is less than the upper bound entry, decide on the replacement entry.

When play begins: repeat with N running from 1 to 5: let P be a random price between 0.00 and 1.00; say "[P] -> [standardized value of P]."; end the story.</lang>

J

Solution: <lang j>le =: -0.96 0.91 0.86 0.81 0.76 0.71 0.66 0.61 0.56 0.51 0.46 0.41 0.36 0.31 0.26 0.21 0.16 0.11 0.06 0.0 out =: 1.00 0.98 0.94 0.90 0.86 0.82 0.78 0.74 0.70 0.66 0.62 0.58 0.54 0.50 0.44 0.38 0.32 0.26 0.18 0.1

priceFraction =: out {~ le I. -</lang>

Example: <lang j> priceFraction 0.34 0.070145 0.06 0.05 0.50214 0.56 1 0.99 0 0.5 0.18 0.18 0.1 0.62 0.7 1 1 0.1</lang>

This implementation performs a binary search on the boundary values, and then uses the resulting index to select from the result values.

To prevent J's binary search from doing the wrong thing for values equal to a boundary, both the boundary values and the search value are negated.

Java

<lang java>import java.util.Random;

public class Main { private static float priceFraction(float f) { if (0.00f <= f && f < 0.06f) return 0.10f; else if (f < 0.11f) return 0.18f; else if (f < 0.16f) return 0.26f; else if (f < 0.21f) return 0.32f; else if (f < 0.26f) return 0.38f; else if (f < 0.31f) return 0.44f; else if (f < 0.36f) return 0.50f; else if (f < 0.41f) return 0.54f; else if (f < 0.46f) return 0.58f; else if (f < 0.51f) return 0.62f; else if (f < 0.56f) return 0.66f; else if (f < 0.61f) return 0.70f; else if (f < 0.66f) return 0.74f; else if (f < 0.71f) return 0.78f; else if (f < 0.76f) return 0.82f; else if (f < 0.81f) return 0.86f; else if (f < 0.86f) return 0.90f; else if (f < 0.91f) return 0.94f; else if (f < 0.96f) return 0.98f; else if (f < 1.01f) return 1.00f; else throw new IllegalArgumentException(); }

public static void main(String[] args) { Random rnd = new Random(); for (int i = 0; i < 5; i++) { float f = rnd.nextFloat(); System.out.format("%8.6f -> %4.2f%n", f, priceFraction(f)); } } }</lang>

Output:
0.149969 -> 0.26
0.310605 -> 0.50
0.616683 -> 0.74
0.194047 -> 0.32
0.724852 -> 0.82

JavaScript

In the task definition, the first step is 0.06, the rest are 0.05 so a re-factoring can subtract 0.01 from the value and divide by 0.05 to get the step.

Working with decimal numbers in JavaScript has issues, e.g. 0.06 - 0.01 = 0.049999999999999996 due to using IEEE 754 double precision numbers that can't accurately represent all decimals. So values are multiplied by 100 and integer arithmetic is used.

Note that multiplying a string by a number produces a number, the bitwise OR (|) truncates floating point numbers to integer, making it a concise replacement for Math.floor.

Passing a value outside the range 0 <= x < 1.01 will return undefined.

<lang javascript>function getScaleFactor(v) {

 var values = ['0.10','0.18','0.26','0.32','0.38','0.44','0.50','0.54',
               '0.58','0.62','0.66','0.70','0.74','0.78','0.82','0.86',
               '0.90','0.94','0.98','1.00'];
 return values[(v * 100 - 1) / 5 | 0];

}</lang>

jq

The solution given here is based on the JavaScript solution. <lang jq>def getScaleFactor:

 ["0.10","0.18","0.26","0.32","0.38","0.44","0.50","0.54",
  "0.58","0.62","0.66","0.70","0.74","0.78","0.82","0.86",
  "0.90","0.94","0.98","1.00"] as $values
 | $values[ (. * 100 - 1) / 5 | floor ] ;</lang>

The full coverage test as given in the Ada example: <lang jq>def test:

 (range(0;10)  | "0.0\(.) -> \( 0.01 * . | getScaleFactor)"),
 (range(10;100) | "0.\(.) -> \( 0.01 * . | getScaleFactor)");

test</lang> Run the test, showing the first few lines of output:

$ jq -n -r -f Price_fraction.jq
0.00 -> 1.00
0.01 -> 0.10
0.02 -> 0.10
0.03 -> 0.10
0.04 -> 0.10
0.05 -> 0.10
0.06 -> 0.18
0.07 -> 0.18
0.08 -> 0.18
0.09 -> 0.18
0.10 -> 0.18
0.11 -> 0.26
...

Julia

This solution is somewhat straightforward but does highlight a couple of Julia features. The interval cut-offs and values are exactly represented by rational numbers. The interval to which an input value belongs is identified by applying the findfirst (true value) function to an element-wise comparison (.<) of this value to the cut-off array. <lang Julia> const PFCUT = [6:5:101]//100 const PFVAL = [10:8:26, 32:6:50, 54:4:98, 100]//100

function pricefraction{T<:FloatingPoint}(a::T)

   zero(T) <= a || error("a = ", a, ", but it must be >= 0.")
   a <= one(T) || error("a = ", a, ", but it must be <= 1.")
   convert(T, PFVAL[findfirst(a .< PFCUT)])

end

test = [0.:0.05:1., 0.51, 0.56, 0.61, rand(), rand(), rand(), rand()]

println("Testing the price fraction function") for t in test

   println(@sprintf "    %.4f -> %.4f" t pricefraction(t))

end </lang>

Output:
Testing the price fraction function
    0.0000 -> 0.1000
    0.0500 -> 0.1000
    0.1000 -> 0.1800
    0.1500 -> 0.2600
    0.2000 -> 0.3200
    0.2500 -> 0.3800
    0.3000 -> 0.4400
    0.3500 -> 0.5000
    0.4000 -> 0.5400
    0.4500 -> 0.5800
    0.5000 -> 0.6200
    0.5500 -> 0.6600
    0.6000 -> 0.7000
    0.6500 -> 0.7400
    0.7000 -> 0.7800
    0.7500 -> 0.8200
    0.8000 -> 0.8600
    0.8500 -> 0.9000
    0.9000 -> 0.9400
    0.9500 -> 0.9800
    1.0000 -> 1.0000
    0.5100 -> 0.6600
    0.5600 -> 0.7000
    0.6100 -> 0.7400
    0.5603 -> 0.7000
    0.9812 -> 1.0000
    0.5127 -> 0.6600
    0.4821 -> 0.6200

K

Translation of the J solution:

<lang K> le:- 0.96 0.91 0.86 0.81 0.76 0.71 0.66 0.61 0.56 0.51 0.46 0.41 0.36 0.31 0.26 0.21 0.16 0.11 0.06 0.0 out: 1.00 0.98 0.94 0.90 0.86 0.82 0.78 0.74 0.70 0.66 0.62 0.58 0.54 0.50 0.44 0.38 0.32 0.26 0.18 0.1

pf:{out@_bin[le;-x]}' </lang>

Output:
   pf 0.6094701 0.5003597 0.8512954 0.08951883 0.6868076
0.7 0.62 0.9 0.18 0.78

Kotlin

<lang scala>// version 1.0.6

fun rescale(price: Double): Double =

   when {
       price < 0.06 ->  0.10
       price < 0.11 ->  0.18
       price < 0.16 ->  0.26
       price < 0.21 ->  0.32
       price < 0.26 ->  0.38
       price < 0.31 ->  0.44
       price < 0.36 ->  0.50
       price < 0.41 ->  0.54
       price < 0.46 ->  0.58
       price < 0.51 ->  0.62
       price < 0.56 ->  0.66
       price < 0.61 ->  0.70
       price < 0.66 ->  0.74
       price < 0.71 ->  0.78
       price < 0.76 ->  0.82
       price < 0.81 ->  0.86
       price < 0.86 ->  0.90
       price < 0.91 ->  0.94
       price < 0.96 ->  0.98
       else         ->  1.00
   }

fun main(args: Array<String>) {

   var d: Double
   for (i in 1..100) {
       d = i / 100.0
       print(String.format("%4.2f -> %4.2f  ", d, rescale(d)))
       if (i % 5 == 0) println()
   }  

}</lang>

Output:
0.01 -> 0.10  0.02 -> 0.10  0.03 -> 0.10  0.04 -> 0.10  0.05 -> 0.10
0.06 -> 0.18  0.07 -> 0.18  0.08 -> 0.18  0.09 -> 0.18  0.10 -> 0.18
0.11 -> 0.26  0.12 -> 0.26  0.13 -> 0.26  0.14 -> 0.26  0.15 -> 0.26
0.16 -> 0.32  0.17 -> 0.32  0.18 -> 0.32  0.19 -> 0.32  0.20 -> 0.32
0.21 -> 0.38  0.22 -> 0.38  0.23 -> 0.38  0.24 -> 0.38  0.25 -> 0.38
0.26 -> 0.44  0.27 -> 0.44  0.28 -> 0.44  0.29 -> 0.44  0.30 -> 0.44
0.31 -> 0.50  0.32 -> 0.50  0.33 -> 0.50  0.34 -> 0.50  0.35 -> 0.50
0.36 -> 0.54  0.37 -> 0.54  0.38 -> 0.54  0.39 -> 0.54  0.40 -> 0.54
0.41 -> 0.58  0.42 -> 0.58  0.43 -> 0.58  0.44 -> 0.58  0.45 -> 0.58
0.46 -> 0.62  0.47 -> 0.62  0.48 -> 0.62  0.49 -> 0.62  0.50 -> 0.62
0.51 -> 0.66  0.52 -> 0.66  0.53 -> 0.66  0.54 -> 0.66  0.55 -> 0.66
0.56 -> 0.70  0.57 -> 0.70  0.58 -> 0.70  0.59 -> 0.70  0.60 -> 0.70
0.61 -> 0.74  0.62 -> 0.74  0.63 -> 0.74  0.64 -> 0.74  0.65 -> 0.74
0.66 -> 0.78  0.67 -> 0.78  0.68 -> 0.78  0.69 -> 0.78  0.70 -> 0.78
0.71 -> 0.82  0.72 -> 0.82  0.73 -> 0.82  0.74 -> 0.82  0.75 -> 0.82
0.76 -> 0.86  0.77 -> 0.86  0.78 -> 0.86  0.79 -> 0.86  0.80 -> 0.86
0.81 -> 0.90  0.82 -> 0.90  0.83 -> 0.90  0.84 -> 0.90  0.85 -> 0.90
0.86 -> 0.94  0.87 -> 0.94  0.88 -> 0.94  0.89 -> 0.94  0.90 -> 0.94
0.91 -> 0.98  0.92 -> 0.98  0.93 -> 0.98  0.94 -> 0.98  0.95 -> 0.98
0.96 -> 1.00  0.97 -> 1.00  0.98 -> 1.00  0.99 -> 1.00  1.00 -> 1.00

langur

Langur uses decimal floating point.

<lang langur># using an implied parameter .f ... val .pricefrac = f given .f {

   case >= 0.00, < 0.06: 0.10
   case >= 0.06, < 0.11: 0.18
   case >= 0.11, < 0.16: 0.26
   case >= 0.16, < 0.21: 0.32
   case >= 0.21, < 0.26: 0.38
   case >= 0.26, < 0.31: 0.44
   case >= 0.31, < 0.36: 0.50
   case >= 0.36, < 0.41: 0.54
   case >= 0.41, < 0.46: 0.58
   case >= 0.46, < 0.51: 0.62
   case >= 0.51, < 0.56: 0.66
   case >= 0.56, < 0.61: 0.70
   case >= 0.61, < 0.66: 0.74
   case >= 0.66, < 0.71: 0.78
   case >= 0.71, < 0.76: 0.82
   case >= 0.76, < 0.81: 0.86
   case >= 0.81, < 0.86: 0.90
   case >= 0.86, < 0.91: 0.94
   case >= 0.91, < 0.96: 0.98
   case >= 0.96, <= 1.00: 1.00
   default: throw "bad data"
   # The default operator between test cases is "and".
   # That is, writing "case" without a logical operator is the same as writing "case and".
   # To make a given case act as a switch case does in other languages, use "case or".

}

writeln .pricefrac(0.17) writeln .pricefrac(0.71)</lang>

Output:
0.32
0.82

Liberty BASIC

<lang lb> dim DR(38) 'decimal range dim PF(38) 'corresponding price fraction range$="0.06 0.11 0.16 0.21 0.26 0.31 0.36 0.41 0.46 0.51 0.56 0.61 0.66 0.71 0.76 0.81 0.86 0.91 0.96 0.01" frac$="0.10 0.18 0.26 0.32 0.38 0.44 0.50 0.54 0.58 0.62 0.66 0.70 0.74 0.78 0.82 0.86 0.90 0.94 0.98 1.00" for i = 1 to 38

 DR(i)=val(word$(range$,i))
 PF(i)=val(word$(frac$,i))

next

for i = 0 to .99 step 0.03

 print i;" -> ";PriceFraction(i)

next end

Function PriceFraction(n)

   PriceFraction=n  'return original if outside test bounds
   for i = 1 to 38
   if n<=DR(i) then
       PriceFraction=PF(i)
       exit for
   end if
   next
   end function

</lang>

Lua

<lang lua>scaleTable = {

   {0.06, 0.10}, {0.11, 0.18}, {0.16, 0.26}, {0.21, 0.32},
   {0.26, 0.38}, {0.31, 0.44}, {0.36, 0.50}, {0.41, 0.54},
   {0.46, 0.58}, {0.51, 0.62}, {0.56, 0.66}, {0.61, 0.70},
   {0.66, 0.74}, {0.71, 0.78}, {0.76, 0.82}, {0.81, 0.86},
   {0.86, 0.90}, {0.91, 0.94}, {0.96, 0.98}, {1.01, 1.00}

}

function rescale (price)

   if price < 0 or price > 1 then return "Out of range!" end
   for k, v in pairs(scaleTable) do
       if price < v[1] then return v[2] end
   end

end

math.randomseed(os.time()) for i = 1, 5 do

   rnd = math.random()
   print("Random value:", rnd)
   print("Adjusted price:", rescale(rnd))
   print()

end</lang>

Output:
Random value:   0.61946413522022
Adjusted price: 0.74

Random value:   0.81141947958698
Adjusted price: 0.9

Random value:   0.55691473099814
Adjusted price: 0.66

Random value:   0.19704311677601
Adjusted price: 0.32

Random value:   0.36528313938816
Adjusted price: 0.54

Maple

<lang maple>priceFraction := proc(price) local values, standard, newPrice, i; values := [0, 0.06, 0.11, 0.16, 0.21, 0.26, 0.31, 0.36, 0.41, 0.46, 0.51, 0.56, 0.61, 0.66, 0.71, 0.76, 0.81, 0.86, 0.91, 0.96, 1.01]; standard := [0.10, 0.18, 0.26, 0.32, 0.38, 0.44, 0.50, 0.54, 0.58, 0.62, 0.66, 0.70, 0.74, 0.78, 0.82, 0.86, 0.90, 0.94, 0.98, 1.00]; for i to numelems(standard) do if price >= values[i] and price < values[i+1] then newPrice := standard[i]; end if; end do; printf("%f --> %.2f\n", price, newPrice); end proc:

randomize(): for i to 5 do priceFraction (rand(0.0..1.0)()); end do;</lang>

Output:
0.524386 --> 0.66
0.887957 --> 0.94
0.670196 --> 0.78
0.875601 --> 0.94
0.540447 --> 0.66

Mathematica/Wolfram Language

<lang Mathematica>PriceFraction[x_]:=Piecewise[{{.1, 0 <= x < 0.06}, {.18, x < .11}, {.26,x < 0.16}, {.32, x < .21}, {.38, x < .26}, {.44, x < 0.31}, {.5, x < .36}, {.54, x < .41}, {.58, x < .46}, {.62, x < .51}, {.66, x < .56}, {.70, x < .61}, {.74, x < .66}, {.78, x < .71}, {.82, x < .76}, {.86, x < .81}, {.90, x < .86}, {.94, x < .91}, {.98, x < .96}}, 1]</lang>

MATLAB / Octave

<lang Matlab> function y = rescale(x)

    L = [0,.06:.05:1.02];
    V = [.1,.18,.26,.32,.38,.44,.50,.54,.58,.62,.66,.70,.74,.78,.82,.86,.9,.94,.98,1];
    y = x; 
    for k=1:numel(x); 
       y(k) = V(sum(L<=x(k)));
    end;
 end;
  t=0:0.001:1;
  plot(t,rescale(t)); </lang>

Mercury

<lang Mercury>:- module price.

- interface.
- import_module int.
- type price == int.
- func standard(price) = price.
- implementation.
- import_module require, list.

standard(P) = SP :-

       require(P >= 0, "P must be positive"),
       Cents = P `mod` 100,
       P + adjust(Cents) = SP.
- func adjust(int) = int.

adjust(Cents) = adjust(Cents, rules).

- func adjust(int, list(price_rule)) = int.

adjust(_, []) = unexpected("price", "adjust/2", "exhausted rules"). adjust(N, [rule(Low, High, To)|T]) = R :-

       ( N >= Low, N < High -> To - N = R ; adjust(N, T) = R ).
- type price_rule ---> rule(int, int, int).
- func rules = list(price_rule).

rules = [rule(00, 06, 10),

       rule(06, 11, 18),
       rule(11, 16, 26),
       rule(16, 21, 32),
       rule(21, 26, 38),
       rule(26, 31, 44),
       rule(31, 36, 50),
       rule(36, 41, 54),
       rule(41, 46, 58),
       rule(46, 51, 62),
       rule(51, 56, 66),
       rule(56, 61, 70),
       rule(61, 66, 74),
       rule(66, 71, 78),
       rule(71, 76, 82),
       rule(76, 81, 86),
       rule(81, 86, 90),
       rule(86, 91, 94),
       rule(91, 96, 98),
       rule(96, 101, 100)].</lang>

A build system might turn the text of the table into the definition of a hundred-element array of adjustments. In that case,

<lang Mercury>adjust(Cents) = array.lookup(price_table, Cents).</lang>

MUMPS

<lang MUMPS>PRICFRAC(X)

;Outputs a specified value dependent upon the input value
;The non-inclusive upper limits are encoded in the PFMAX string, and the values
;to convert to are encoded in the PFRES string.
NEW PFMAX,PFRES,I,RESULT
SET PFMAX=".06^.11^.16^.21^.26^.31^.36^.41^.46^.51^.56^.61^.66^.71^.76^.81^.86^.91^.96^1.01"
SET PFRES=".10^.18^.26^.32^.38^.44^.50^.54^.58^.62^.66^.70^.74^.78^.82^.86^.90^.94^.98^1.00"
Q:(X<0)!(X>1.01) ""
FOR I=1:1:$LENGTH(PFMAX,"^") Q:($DATA(RESULT)'=0)  SET:X<$P(PFMAX,"^",I) RESULT=$P(PFRES,"^",I)
KILL PFMAX,PFRES,I
QUIT RESULT</lang>
Output:
USER>W $$PRICFRAC^ROSETTA(.04)
.10
USER>W $$PRICFRAC^ROSETTA(.06)
.18
USER>W $$PRICFRAC^ROSETTA(.40)
.54
USER>W $$PRICFRAC^ROSETTA(1.40)
 
USER>W $$PRICFRAC^ROSETTA(.81)
.90

NetRexx

<lang NetRexx>/* NetRexx */ options replace format comments java crossref symbols nobinary

runSample(arg) return

-- ----------------------------------------------------------------------------- method runSample(arg) public static

 parse arg in_val .
 if in_val \=  then test_vals = [in_val]
 else                 test_vals = getTestData()
 say 'Input Adjustment'
 loop tv = 0 to test_vals.length - 1
   in_val = test_vals[tv]
   adjust = priceFraction(in_val)
   say in_val.format(null, 2).right(5) adjust.format(null, 2).right(10)
   end tv
 return

-- ----------------------------------------------------------------------------- method priceFraction(in_val) public static

 out_val = -1
 limit_table = getLimitTable()
 limit_table_K = limit_table.length
 loop p1 = 0 to limit_table_K - 1
   pair = limit_table[p1]
   hi_limit = pair[0]
   adjustmt = pair[1]
   if in_val < hi_limit then do
     out_val = adjustmt
     leave p1
     end
   end p1
 if out_val = -1 then signal IllegalArgumentException('Input' in_val 'is outside of acceptable range.')
 return out_val

-- ----------------------------------------------------------------------------- method getLimitTable() public static returns Rexx[,]

 limit_table = [ -
   [0.06, 0.10], [0.11, 0.18], [0.16, 0.26], [0.21, 0.32], [0.26, 0.38], -
   [0.31, 0.44], [0.36, 0.50], [0.41, 0.54], [0.46, 0.58], [0.51, 0.62], -
   [0.56, 0.66], [0.61, 0.70], [0.66, 0.74], [0.71, 0.78], [0.76, 0.82], -
   [0.81, 0.86], [0.86, 0.90], [0.91, 0.94], [0.96, 0.98], [1.01, 1.00]  -
 ]
 return limit_table

-- ----------------------------------------------------------------------------- method getTestData() private static returns Rexx[]

 test_vals = Rexx[5]
 rng = Random(1024)
 loop tv = 0 to test_vals.length - 1
   test_vals[tv] = rng.nextFloat()
   end tv
 return test_vals

</lang>

Output:
Input Adjustment
 0.64       0.74
 0.32       0.50
 0.85       0.90
 0.93       0.98
 0.62       0.74

Nim

<lang nim>import random, strformat

  1. Representation of a standard value as an int (actual value * 100).

type StandardValue = distinct int

proc `<`(a, b: StandardValue): bool {.borrow.}

const Pricemap = [10, 18, 26, 32, 38, 44, 50, 54, 58, 62, 66, 70, 74, 78, 82, 86, 90, 94, 98, 100]


proc toStandardValue(f: float): StandardValue =

 ## Convert a float to a standard value (decimal value multiplied by 100).
 ## Index: 0.01..0.05 -> 0, 0.06..0.10 -> 1, 0.11..0.15 -> 2...
 var value = int(f * 100)
 if value == 0: return StandardValue(10)
 dec value
 # Increment index every 5 of value, so value in 1..100 translates to index in 0..19.
 let index = 2 * (value div 10) + (value mod 10) div 5
 result = StandardValue(Pricemap[index])


proc `$`(price: StandardValue): string =

 ## Return the string representation of a standard value.
 if price < StandardValue(10): "0.0" & $int(price)
 elif price < StandardValue(100): "0." & $int(price)
 else: "1.00"


when isMainModule:

 randomize()
 for _ in 0 .. 10:
   let price = rand(1.01)
   echo &"Price for {price:.2f} is {price.toStandardValue()}"</lang>
Output:

A random output looking something like this:

Price for 0.88 is 0.94
Price for 0.58 is 0.70
Price for 0.67 is 0.78
Price for 0.53 is 0.66
Price for 0.56 is 0.66
Price for 0.02 is 0.10
Price for 0.61 is 0.70
Price for 0.41 is 0.58
Price for 0.22 is 0.38
Price for 0.91 is 0.98
Price for 0.42 is 0.58

Objeck

Translation of: C#

<lang objeck>class PriceFraction {

 function : Main(args : String[]) ~ Nil {
   for(i := 0; i < 5; i++;) {
     f := Float->Random();
     r := SpecialRound(f);
     "{$f} -> {$r}"->PrintLine();
   };
 }
 function : SpecialRound(inValue : Float) ~ Float {
   if (inValue > 1) {
     return 1;
   };
   splitters := [  
     0.00 , 0.06 , 0.11 , 0.16 , 0.21 , 
     0.26 , 0.31 , 0.36 , 0.41 , 0.46 , 
     0.51 , 0.56 , 0.61 , 0.66 , 0.71 , 
     0.76 , 0.81 , 0.86 , 0.91 , 0.96 ];
   replacements := [ 
     0.10 , 0.18 , 0.26 , 0.32 , 0.38 ,
     0.44 , 0.50 , 0.54 , 0.58 , 0.62 , 
     0.66 , 0.70 , 0.74 , 0.78 , 0.82 , 
     0.86 , 0.90 , 0.94 , 0.98 , 1.00 ];
   for(x := 0; x < splitters->Size() - 1; x+=1;) {
     if (inValue >= splitters[x] & inValue < splitters[x + 1]) {
       return replacements[x];
     };
   };
   return inValue;
 }

}</lang>

Output:
0.317901 -> 0.5
0.691109 -> 0.78
0.790891 -> 0.86
0.269922 -> 0.44
0.690891 -> 0.78

OCaml

<lang ocaml>let price_fraction v =

 if v < 0.0 || v >= 1.01 then
   invalid_arg "price_fraction";
 let rec aux = function
 | (x,r)::tl ->
     if v < x then r
     else aux tl
 | [] -> assert false
 in
 aux [
   0.06, 0.10;   0.11, 0.18;   0.16, 0.26;   0.21, 0.32;   0.26, 0.38;
   0.31, 0.44;   0.36, 0.50;   0.41, 0.54;   0.46, 0.58;   0.51, 0.62;
   0.56, 0.66;   0.61, 0.70;   0.66, 0.74;   0.71, 0.78;   0.76, 0.82;
   0.81, 0.86;   0.86, 0.90;   0.91, 0.94;   0.96, 0.98;   1.01, 1.00;
 ]</lang>

<lang ocaml>let () =

 let ok_tests = [
   (0.3793, 0.54);
   (0.4425, 0.58);
   (0.0746, 0.18);
   (0.6918, 0.78);
   (0.2993, 0.44);
   (0.5486, 0.66);
   (0.7848, 0.86);
   (0.9383, 0.98);
   (0.2292, 0.38);
 ] in
 Printf.printf " input   res   ok\n";
 List.iter (fun (v,ok) ->
   let r = price_fraction v in
   Printf.printf " %6g  %g  %b\n" v r (r = ok);
 ) ok_tests;
</lang>

Oforth

<lang oforth>[.06, .11, .16, .21, .26, .31, .36, .41, .46, .51, .56, .61, .66, .71, .76, .81, .86, .91, .96, 1.01] const: IN [.10, .18, .26, .32, .38, .44, .50, .54, .58, .62, .66, .70, .74, .78, .82, .86, .90, .94, .98, 1.00] const: OUT

priceFraction(f)

| i |

  IN size loop: i [ f IN at(i) < ifTrue: [ OUT at(i) return ] ]
  null ;</lang>
Output:
>[0.7388727, 0.8593103, 0.826687, 0.3444635] map(#priceFraction) .
[0.82, 0.9, 0.9, 0.5] ok

Oz

Using a for-loop with return and a default value for values >= 1.01. For out-of-range input, a "failed value" is returned, i.e. a value that throws an exception when it is accessed.

<lang oz>fun {PriceFraction X}

  OutOfRange = {Value.failed outOfRange(X)}

in

  for Limit#Result in
     [0.00#OutOfRange
      0.06#0.10 0.11#0.18 0.16#0.26 0.21#0.32 0.26#0.38 0.31#0.44 0.36#0.5
      0.41#0.54 0.46#0.58 0.51#0.62 0.56#0.66 0.61#0.70 0.66#0.74 0.71#0.78
      0.76#0.82 0.81#0.86 0.86#0.90 0.91#0.94 0.96#0.98 1.01#1.00
     ]
     return:Return
     default:OutOfRange
  do
     if X < Limit then {Return Result} end 
  end

end</lang>

PARI/GP

<lang parigp>priceLookup=[6,11,16,21,26,31,41,46,51,56,61,66,71,76,81,86,91,96,101]; priceReplace=[10,18,26,32,38,44,50,54,58,62,66,70,74,78,82,86,90,94,98,100]; pf(x)={

 x*=100;
 for(i=1,19,
   if(x<priceLookup[i], return(priceReplace[i]))
 );
 "nasal demons"

};</lang>

Pascal

<lang pascal>Program PriceFraction(output);

const

 limit: array [1..20] of real = 
          (0.06, 0.11, 0.16, 0.21, 0.26, 0.31, 0.36, 0.41, 0.46, 0.51,
           0.56, 0.61, 0.66, 0.71, 0.76, 0.81, 0.86, 0.91, 0.96, 1.01);
 price: array [1..20] of real = 
          (0.10, 0.18, 0.26, 0.32, 0.38, 0.44, 0.50, 0.54, 0.58, 0.62,
           0.66, 0.70, 0.74, 0.78, 0.81, 0.86, 0.90, 0.94, 0.98, 1.00);

var

 cost: real;
 i, j: integer;

begin

 randomize;
 for i := 1 to 10 do
 begin
   cost := random;
   j := high(limit);
   while cost < limit[j] do
     dec(j);
   writeln (cost:6:4, ' -> ', price[j+1]:4:2);
 end;

end.</lang>

Output:
% ./PriceFraction
0.8145 -> 0.90
0.6347 -> 0.74
0.0464 -> 0.10
0.9603 -> 1.00
0.3629 -> 0.54
0.5074 -> 0.62
0.4516 -> 0.58
0.2340 -> 0.38
0.4142 -> 0.58
0.8327 -> 0.90

Perl

<lang Perl>my @table = map [ /([\d\.]+)/g ], split "\n", <<'TBL'; >= 0.00 < 0.06  := 0.10 >= 0.06 < 0.11  := 0.18 >= 0.11 < 0.16  := 0.26 >= 0.16 < 0.21  := 0.32 >= 0.21 < 0.26  := 0.38 >= 0.26 < 0.31  := 0.44 >= 0.31 < 0.36  := 0.50 >= 0.36 < 0.41  := 0.54 >= 0.41 < 0.46  := 0.58 >= 0.46 < 0.51  := 0.62 >= 0.51 < 0.56  := 0.66 >= 0.56 < 0.61  := 0.70 >= 0.61 < 0.66  := 0.74 >= 0.66 < 0.71  := 0.78 >= 0.71 < 0.76  := 0.82 >= 0.76 < 0.81  := 0.86 >= 0.81 < 0.86  := 0.90 >= 0.86 < 0.91  := 0.94 >= 0.91 < 0.96  := 0.98 >= 0.96 < 1.01  := 1.00 TBL

sub convert {

       my $money = shift;
       for (@table) {
               return $_->[2] if $_->[0] <= $money and $_->[1] > $money
       }
       die "Can't find currency conversion for $money. Counterfeit?"

}

  1. try it out

for (1 .. 10) {

       my $m = rand(1);
       printf "%.3f -> %g\n", $m, convert($m);

} </lang>

Phix

<lang Phix>constant TBL=split(""" >= 0.00 < 0.06  := 0.10 >= 0.06 < 0.11  := 0.18 >= 0.11 < 0.16  := 0.26 >= 0.16 < 0.21  := 0.32 >= 0.21 < 0.26  := 0.38 >= 0.26 < 0.31  := 0.44 >= 0.31 < 0.36  := 0.50 >= 0.36 < 0.41  := 0.54 >= 0.41 < 0.46  := 0.58 >= 0.46 < 0.51  := 0.62 >= 0.51 < 0.56  := 0.66 >= 0.56 < 0.61  := 0.70 >= 0.61 < 0.66  := 0.74 >= 0.66 < 0.71  := 0.78 >= 0.71 < 0.76  := 0.82 >= 0.76 < 0.81  := 0.86 >= 0.81 < 0.86  := 0.90 >= 0.86 < 0.91  := 0.94 >= 0.91 < 0.96  := 0.98 >= 0.96 < 1.01  := 1.00""",'\n')

sequence limits = {0},

        prices = {-1}

atom lt,price for i=1 to length(TBL) do

   Template:?,lt,price = scanf(TBL[i],">=  %.2f  <  %.2f  :=  %.2f")
   limits = append(limits,lt)
   prices = append(prices,price)

end for

function price_fix(atom p)

   for i=1 to length(limits) do
       if p<limits[i] then
           return prices[i]
       end if
   end for
   return -1

end function

for i=-1 to 101 do

   printf(1, "%5.2f %5.2f\n", {i/100,price_fix(i/100)})

end for</lang>

Phixmonti

<lang Phixmonti>include ..\Utilitys.pmt

( ( 0.00 0.06 0.10 ) ( 0.06 0.11 0.18 ) ( 0.11 0.16 0.26 ) ( 0.16 0.21 0.32 ) ( 0.21 0.26 0.38 ) ( 0.26 0.31 0.44 ) ( 0.31 0.36 0.50 ) ( 0.36 0.41 0.54 ) ( 0.41 0.46 0.58 ) ( 0.46 0.51 0.62 ) ( 0.51 0.56 0.66 ) ( 0.56 0.61 0.70 ) ( 0.61 0.66 0.74 ) ( 0.66 0.71 0.78 ) ( 0.71 0.76 0.82 ) ( 0.76 0.81 0.86 ) ( 0.81 0.86 0.90 ) ( 0.86 0.91 0.94 ) ( 0.91 0.96 0.98 ) ( 0.96 1.01 1.00 ) )

def price_fix

   var p
   len for
       get
       3 get swap 1 get swap 2 get nip
       p swap < swap p swap >=
       and if
           exitfor
       else
           drop
       endif
   endfor

enddef

( 0.00 1.01 0.01 ) for

   dup print 9 tochar print price_fix print nl 

endfor </lang>

PicoLisp

<lang PicoLisp>(scl 2)

(de price (Pr)

  (format
     (cdr
        (rank Pr
           (quote
              (0.00 . 0.10)
              (0.06 . 0.18)
              (0.11 . 0.26)
              (0.16 . 0.32)
              (0.21 . 0.38)
              (0.26 . 0.44)
              (0.31 . 0.50)
              (0.36 . 0.54)
              (0.41 . 0.58)
              (0.46 . 0.62)
              (0.51 . 0.66)
              (0.56 . 0.70)
              (0.61 . 0.74)
              (0.66 . 0.78)
              (0.71 . 0.82)
              (0.76 . 0.86)
              (0.81 . 0.90)
              (0.86 . 0.94)
              (0.91 . 0.98)
              (0.96 . 1.00) ) ) )
     *Scl ) )

(for N (0.3793 0.4425 0.0746 0.6918 0.2993 0.5486 0.7848 0.9383 0.2292)

  (prinl (price N)) )</lang>
Output:
0.54
0.58
0.18
0.78
0.44
0.66
0.86
0.98
0.38

PL/I

version 1

<lang PL/I>declare t(20) fixed decimal (3,2) static initial (

  .06, .11, .16, .21, .26, .31, .36, .41, .46,  .51,
  .56, .61, .66, .71, .76, .81, .86, .91, .96, 1.01);

declare r(20) fixed decimal (3,2) static initial (

  .10, .18, .26, .32, .38, .44, .50, .54, .58, .62,
  .66, .70, .74, .78, .82, .86, .90, .94, .98, 1);

declare x float, d fixed decimal (3,2); declare i fixed binary;

loop:

  do i = 1 to 20;
     if x < t(i) then
        do; d = r(i); leave loop; end;
  end;</lang>

version 2

Translation of: REXX version2
<lang PL/I>cpt: Proc Options(main); 
Dcl x Dec Fixed(4,2);
Do x=0 To 1 By 0.01;
  Put Edit(x,' -> ',cp(x))(Skip,f(4,2),a,f(4,2));
  End;
cp: Proc(p) Returns(Dec Fixed(4,2));
Dcl r(20) Dec Fixed(4,2) static init(
  .10, .18, .26, .32, .38, .44, .50, .54, .58, .62,
  .66, .70, .74, .78, .82, .86, .90, .94, .98, 1);
Dcl p Dec Fixed(4,2);
Dcl i Bin Fixed;
i=trunc((100*p-1)/5)+1;
Return(r(i));
End;
End;</lang>

PowerShell

<lang PowerShell> function Convert-PriceFraction {

   [CmdletBinding()]
   [OutputType([double])]
   Param
   (
       [Parameter(Mandatory=$true,
                  ValueFromPipeline=$true,
                  ValueFromPipelineByPropertyName=$true,
                  Position=0)]
       [ValidateScript({$_ -ge 0.0 -and $_ -le 1.0})]
       [double]
       $InputObject
   )
   Process
   {
       foreach ($fraction in $InputObject)
       {
           switch ($fraction)
           {
               {$_ -lt 0.06} {0.10; break}
               {$_ -lt 0.11} {0.18; break}
               {$_ -lt 0.16} {0.26; break}
               {$_ -lt 0.21} {0.32; break}
               {$_ -lt 0.26} {0.38; break}
               {$_ -lt 0.31} {0.44; break}
               {$_ -lt 0.36} {0.50; break}
               {$_ -lt 0.41} {0.54; break}
               {$_ -lt 0.46} {0.58; break}
               {$_ -lt 0.51} {0.62; break}
               {$_ -lt 0.56} {0.66; break}
               {$_ -lt 0.61} {0.70; break}
               {$_ -lt 0.66} {0.74; break}
               {$_ -lt 0.71} {0.78; break}
               {$_ -lt 0.76} {0.82; break}
               {$_ -lt 0.81} {0.86; break}
               {$_ -lt 0.86} {0.90; break}
               {$_ -lt 0.91} {0.94; break}
               {$_ -lt 0.96} {0.98; break}
               Default       {1.00}
           }
       }
   }

} </lang> <lang PowerShell> .7388727, .8593103, .826687, .3444635, .0491907 | Convert-PriceFraction | ForEach-Object {"{0:C}" -f $_} </lang>

Output:
$0.82
$0.90
$0.90
$0.50
$0.10

PureBasic

<lang PureBasic>Procedure.f PriceFraction(price.f)

 ;returns price unchanged if value is invalid 
 Protected fraction
 Select price * 100
   Case 0 To 5
     fraction = 10
   Case 06 To 10
     fraction = 18
   Case 11 To 15
     fraction = 26
   Case 16 To 20
     fraction = 32
   Case 21 To 25
     fraction = 38
   Case 26 To 30
     fraction = 44
   Case 31 To 35
     fraction = 5
   Case 36 To 40
     fraction = 54
   Case 41 To 45
     fraction = 58
   Case 46 To 50
     fraction = 62
   Case 51 To 55
     fraction = 66
   Case 56 To 60
     fraction = 7
   Case 61 To 65
     fraction = 74
   Case 66 To 70
     fraction = 78
   Case 71 To 75
     fraction = 82
   Case 76 To 80
     fraction = 86
   Case 81 To 85
     fraction = 9
   Case 86 To 90
     fraction = 94
   Case 91 To 95
     fraction = 98
   Case 96 To 100
     fraction = 100
   Default
     ProcedureReturn price
 EndSelect
 
 ProcedureReturn fraction / 100

EndProcedure

If OpenConsole()

 Define x.f, i
 
 For i = 1 To 10
   x = Random(10000)/10000
   PrintN(StrF(x, 4) + " -> " + StrF(PriceFraction(x), 2))
 Next
 
 Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
 Input()
 CloseConsole()

EndIf</lang>

Output:
0.3793 -> 0.54
0.4425 -> 0.58
0.0746 -> 0.18
0.6918 -> 0.78
0.2993 -> 0.44
0.5486 -> 0.66
0.7848 -> 0.86
0.9383 -> 0.98
0.2292 -> 0.38
0.9560 -> 1.00

Python

Using the bisect standard module to reduce the comparisons with members of the cin array.

<lang python>>>> import bisect >>> _cin = [.06, .11, .16, .21, .26, .31, .36, .41, .46, .51, .56, .61, .66, .71, .76, .81, .86, .91, .96, 1.01] >>> _cout = [.10, .18, .26, .32, .38, .44, .50, .54, .58, .62, .66, .70, .74, .78, .82, .86, .90, .94, .98, 1.00] >>> def pricerounder(pricein): return _cout[ bisect.bisect_right(_cin, pricein) ]</lang>

When dealing with money it is good to think about possible loss of precision. If we change the units to be integer cents we could use the following exact routine: <lang python>>>> import bisect >>> _cin = [ 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76, 81, 86, 91, 96, 101] >>> _cout = [10, 18, 26, 32, 38, 44, 50, 54, 58, 62, 66, 70, 74, 78, 82, 86, 90, 94, 98, 100] >>> def centsrounder(centsin): return _cout[ bisect.bisect_right(_cin, centsin) ]</lang> Other options are to use the fractions or decimals modules for calculating money to a known precision.


Bisection library code

The bisect Python standard library function uses the following code that improves on a simple linear scan through a sorted list:
<lang python>def bisect_right(a, x, lo=0, hi=None):
   """Return the index where to insert item x in list a, assuming a is sorted.
   The return value i is such that all e in a[:i] have e <= x, and all e in
   a[i:] have e > x.  So if x already appears in the list, a.insert(x) will
   insert just after the rightmost x already there.
   Optional args lo (default 0) and hi (default len(a)) bound the
   slice of a to be searched.
   """
   if lo < 0:
       raise ValueError('lo must be non-negative')
   if hi is None:
       hi = len(a)
   while lo < hi:
       mid = (lo+hi)//2
       if x < a[mid]: hi = mid
       else: lo = mid+1
   return lo</lang>

Quackery

This program uses the bignum rationals provided by bigrat.qky, so it avoids the pitfalls of storing money as floating point numbers. <lang quackery>[ $ 'bigrat.qky' loadfile ] now!

[ 2over 2over v< if 2swap 2drop ] is vmax ( n/d n/d --> n/d )

[ 100 1 v* 1 1 v-

 0 1 vmax 5 1 v/ /
 [ table
   10 18 26 32 38
   44 50 54 58 62
   66 70 74 78 82
   86 90 94 98 100 ] 100 ]       is scale ( n/d     --> n/d )

[ swap echo sp echo ] is br ( n/d --> )

[ 2dup br say ' --> '

 scale br cr ]                   is test  ( n/d     -->     )

0 100 test 50 100 test 65 100 test 66 100 test 100 100 test 7368 10000 test

( Show how to enter and display results as a decimal too. ) $ '0.7368' dup echo$ say ' --> ' $->v drop scale 2 point$ echo$</lang>

Output:
0 100 --> 10 100
50 100 --> 62 100
65 100 --> 74 100
66 100 --> 78 100
100 100 --> 100 100
7368 10000 --> 82 100
0.7368 --> 0.82

R

<lang r> price_fraction <- function(x) {

 stopifnot(all(x >= 0 & x <= 1))
 breaks <- seq(0.06, 1.01, 0.05)
 values <- c(.1, .18, .26, .32, .38, .44, .5, .54, .58, .62, .66, .7, .74, .78, .82, .86, .9, .94, .98, 1)
 indices <- sapply(x, function(x) which(x < breaks)[1])
 values[indices]

}

  1. Example usage:

price_fraction(c(0, .01, 0.06, 0.25, 1)) # 0.10 0.10 0.18 0.38 1.00 </lang>

You can extract the contents of the table as follows:

<lang r> dfr <- read.table(tc <- textConnection( ">= 0.00 < 0.06  := 0.10 >= 0.06 < 0.11  := 0.18 >= 0.11 < 0.16  := 0.26 >= 0.16 < 0.21  := 0.32 >= 0.21 < 0.26  := 0.38 >= 0.26 < 0.31  := 0.44 >= 0.31 < 0.36  := 0.50 >= 0.36 < 0.41  := 0.54 >= 0.41 < 0.46  := 0.58 >= 0.46 < 0.51  := 0.62 >= 0.51 < 0.56  := 0.66 >= 0.56 < 0.61  := 0.70 >= 0.61 < 0.66  := 0.74 >= 0.66 < 0.71  := 0.78 >= 0.71 < 0.76  := 0.82 >= 0.76 < 0.81  := 0.86 >= 0.81 < 0.86  := 0.90 >= 0.86 < 0.91  := 0.94 >= 0.91 < 0.96  := 0.98 >= 0.96 < 1.01  := 1.00")); close(tc) breaks <- dfr$V4 values <- dfr$V6 </lang>

Racket

<lang Racket>

  1. lang racket

(define table

 '([0 #f]
   [0.06 0.10] [0.11 0.18] [0.16 0.26] [0.21 0.32] [0.26 0.38] [0.31 0.44]
   [0.36 0.50] [0.41 0.54] [0.46 0.58] [0.51 0.62] [0.56 0.66] [0.61 0.70]
   [0.66 0.74] [0.71 0.78] [0.76 0.82] [0.81 0.86] [0.86 0.90] [0.91 0.94]
   [0.96 0.98] [1.01 1.00])
 ;; returns #f for negatives or values >= 1.01

(define (convert x) (for/or ([c table]) (and (< x (car c)) (cadr c)))) </lang>

Raku

(formerly Perl 6)

Simple solution, doing a linear search.
Note that in Raku we don't have to worry about floating-point misrepresentations of decimals, because decimal fractions are stored as rationals.

Works with: rakudo version 2016.07

<lang perl6>sub price-fraction ($n where 0..1) {

   when $n < 0.06 { 0.10 }
   when $n < 0.11 { 0.18 }
   when $n < 0.16 { 0.26 }
   when $n < 0.21 { 0.32 }
   when $n < 0.26 { 0.38 }
   when $n < 0.31 { 0.44 }
   when $n < 0.36 { 0.50 }
   when $n < 0.41 { 0.54 }
   when $n < 0.46 { 0.58 }
   when $n < 0.51 { 0.62 }
   when $n < 0.56 { 0.66 }
   when $n < 0.61 { 0.70 }
   when $n < 0.66 { 0.74 }
   when $n < 0.71 { 0.78 }
   when $n < 0.76 { 0.82 }
   when $n < 0.81 { 0.86 }
   when $n < 0.86 { 0.90 }
   when $n < 0.91 { 0.94 }
   when $n < 0.96 { 0.98 }
   default        { 1.00 }

}

while prompt("value: ") -> $value {

   say price-fraction(+$value);

}</lang>

If we expect to rescale many prices, a better approach would be to build a look-up array of 101 entries. Memory is cheap, and array indexing is blazing fast.

<lang perl6>my @price = map *.value, flat

   ( 0 ..^ 6  X=> 0.10),
   ( 6 ..^ 11 X=> 0.18),
   (11 ..^ 16 X=> 0.26),
   (16 ..^ 21 X=> 0.32),
   (21 ..^ 26 X=> 0.38),
   (26 ..^ 31 X=> 0.44),
   (31 ..^ 36 X=> 0.50),
   (36 ..^ 41 X=> 0.54),
   (41 ..^ 46 X=> 0.58),
   (46 ..^ 51 X=> 0.62),
   (51 ..^ 56 X=> 0.66),
   (56 ..^ 61 X=> 0.70),
   (61 ..^ 66 X=> 0.74),
   (66 ..^ 71 X=> 0.78),
   (71 ..^ 76 X=> 0.82),
   (76 ..^ 81 X=> 0.86),
   (81 ..^ 86 X=> 0.90),
   (86 ..^ 91 X=> 0.94),
   (91 ..^ 96 X=> 0.98),
   (96 ..^101 X=> 1.00),

while prompt("value: ") -> $value {

   say @price[$value * 100] // "Out of range";

}</lang>

We can also build this same look-up array by parsing the table as formatted in the task description:

Works with: rakudo version 2016.07

<lang perl6>my $table = q:to/END/; >= 0.00 < 0.06  := 0.10 >= 0.06 < 0.11  := 0.18 >= 0.11 < 0.16  := 0.26 >= 0.16 < 0.21  := 0.32 >= 0.21 < 0.26  := 0.38 >= 0.26 < 0.31  := 0.44 >= 0.31 < 0.36  := 0.50 >= 0.36 < 0.41  := 0.54 >= 0.41 < 0.46  := 0.58 >= 0.46 < 0.51  := 0.62 >= 0.51 < 0.56  := 0.66 >= 0.56 < 0.61  := 0.70 >= 0.61 < 0.66  := 0.74 >= 0.66 < 0.71  := 0.78 >= 0.71 < 0.76  := 0.82 >= 0.76 < 0.81  := 0.86 >= 0.81 < 0.86  := 0.90 >= 0.86 < 0.91  := 0.94 >= 0.91 < 0.96  := 0.98 >= 0.96 < 1.01  := 1.00 END

my @price;

for $table.lines {

   /:s '>='  (\S+)  '<'  (\S+)  ':='  (\S+)/;
   @price[$0*100 ..^ $1*100] »=» +$2;

}

while prompt("value: ") -> $value {

   say @price[$value * 100] // "Out of range";

}</lang>

Raven

Translation of: JavaScript

<lang Raven>define getScaleFactor use $v

  [ 0.1 0.18 0.26 0.32 0.38 0.44 0.50 0.54 0.58 0.62 0.66 0.70 0.74 0.78 0.82 0.86 0.90 0.94 0.98 1.0 ] as $vals
  $v 100 * 1 - 5 /    20 min  0 max  1 prefer dup $v "val: %g  indx: %d\n" print   $vals swap get

0 100 9 range each

   100.0 / dup getScaleFactor swap "%.2g -> %.2g\n" print</lang>
Output:
0 -> 0.1
0.09 -> 0.18
0.18 -> 0.32
0.27 -> 0.44
0.36 -> 0.54
0.45 -> 0.58
0.54 -> 0.66
0.63 -> 0.74
0.72 -> 0.82
0.81 -> 0.9
0.9 -> 0.94
0.99 -> 1

REXX

version 1

<lang rexx>/*REXX program re─scales a (decimal fraction) price (in the range of: 0¢ ──► $1). */ pad= ' ' /*for inserting spaces into a message. */

         do j=0  to 1  by .01                   /*process the prices from 0¢  to  ≤ $1 */
         if j==0  then j= 0.00                  /*handle the special case of zero cents*/
         say pad  'original price ──►'    j   pad   adjPrice(j)     " ◄── adjusted price"
         end   /*j*/

exit 0 /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ adjPrice: procedure; parse arg ? /*a table is used to facilitate changes*/

                                    select
                                    when ?<0.06  then ?= 0.10
                                    when ?<0.11  then ?= 0.18
                                    when ?<0.16  then ?= 0.26
                                    when ?<0.21  then ?= 0.32
                                    when ?<0.26  then ?= 0.38
                                    when ?<0.31  then ?= 0.44
                                    when ?<0.36  then ?= 0.50
                                    when ?<0.41  then ?= 0.54
                                    when ?<0.46  then ?= 0.58
                                    when ?<0.51  then ?= 0.62
                                    when ?<0.56  then ?= 0.66
                                    when ?<0.61  then ?= 0.70
                                    when ?<0.66  then ?= 0.74
                                    when ?<0.71  then ?= 0.78
                                    when ?<0.76  then ?= 0.82
                                    when ?<0.81  then ?= 0.86
                                    when ?<0.86  then ?= 0.90
                                    when ?<0.91  then ?= 0.94
                                    when ?<0.96  then ?= 0.98
                                    when ?<1.01  then ?= 1.00
                                    otherwise    nop
                                    end   /*select*/
         return ?</lang>
output :
      original price ──► 0.00       0.10  ◄── adjusted price
      original price ──► 0.01       0.10  ◄── adjusted price
      original price ──► 0.02       0.10  ◄── adjusted price
      original price ──► 0.03       0.10  ◄── adjusted price
      original price ──► 0.04       0.10  ◄── adjusted price
      original price ──► 0.05       0.10  ◄── adjusted price
      original price ──► 0.06       0.18  ◄── adjusted price
      original price ──► 0.07       0.18  ◄── adjusted price
      original price ──► 0.08       0.18  ◄── adjusted price
      original price ──► 0.09       0.18  ◄── adjusted price
      original price ──► 0.10       0.18  ◄── adjusted price
      original price ──► 0.11       0.26  ◄── adjusted price
      original price ──► 0.12       0.26  ◄── adjusted price
      original price ──► 0.13       0.26  ◄── adjusted price
      original price ──► 0.14       0.26  ◄── adjusted price
      original price ──► 0.15       0.26  ◄── adjusted price
      original price ──► 0.16       0.32  ◄── adjusted price
      original price ──► 0.17       0.32  ◄── adjusted price
      original price ──► 0.18       0.32  ◄── adjusted price
      original price ──► 0.19       0.32  ◄── adjusted price
      original price ──► 0.20       0.32  ◄── adjusted price
      original price ──► 0.21       0.38  ◄── adjusted price
      original price ──► 0.22       0.38  ◄── adjusted price
      original price ──► 0.23       0.38  ◄── adjusted price
      original price ──► 0.24       0.38  ◄── adjusted price
      original price ──► 0.25       0.38  ◄── adjusted price
      original price ──► 0.26       0.44  ◄── adjusted price
      original price ──► 0.27       0.44  ◄── adjusted price
      original price ──► 0.28       0.44  ◄── adjusted price
      original price ──► 0.29       0.44  ◄── adjusted price
      original price ──► 0.30       0.44  ◄── adjusted price
      original price ──► 0.31       0.50  ◄── adjusted price
      original price ──► 0.32       0.50  ◄── adjusted price
      original price ──► 0.33       0.50  ◄── adjusted price
      original price ──► 0.34       0.50  ◄── adjusted price
      original price ──► 0.35       0.50  ◄── adjusted price
      original price ──► 0.36       0.54  ◄── adjusted price
      original price ──► 0.37       0.54  ◄── adjusted price
      original price ──► 0.38       0.54  ◄── adjusted price
      original price ──► 0.39       0.54  ◄── adjusted price
      original price ──► 0.40       0.54  ◄── adjusted price
      original price ──► 0.41       0.58  ◄── adjusted price
      original price ──► 0.42       0.58  ◄── adjusted price
      original price ──► 0.43       0.58  ◄── adjusted price
      original price ──► 0.44       0.58  ◄── adjusted price
      original price ──► 0.45       0.58  ◄── adjusted price
      original price ──► 0.46       0.62  ◄── adjusted price
      original price ──► 0.47       0.62  ◄── adjusted price
      original price ──► 0.48       0.62  ◄── adjusted price
      original price ──► 0.49       0.62  ◄── adjusted price
      original price ──► 0.50       0.62  ◄── adjusted price
      original price ──► 0.51       0.66  ◄── adjusted price
      original price ──► 0.52       0.66  ◄── adjusted price
      original price ──► 0.53       0.66  ◄── adjusted price
      original price ──► 0.54       0.66  ◄── adjusted price
      original price ──► 0.55       0.66  ◄── adjusted price
      original price ──► 0.56       0.70  ◄── adjusted price
      original price ──► 0.57       0.70  ◄── adjusted price
      original price ──► 0.58       0.70  ◄── adjusted price
      original price ──► 0.59       0.70  ◄── adjusted price
      original price ──► 0.60       0.70  ◄── adjusted price
      original price ──► 0.61       0.74  ◄── adjusted price
      original price ──► 0.62       0.74  ◄── adjusted price
      original price ──► 0.63       0.74  ◄── adjusted price
      original price ──► 0.64       0.74  ◄── adjusted price
      original price ──► 0.65       0.74  ◄── adjusted price
      original price ──► 0.66       0.78  ◄── adjusted price
      original price ──► 0.67       0.78  ◄── adjusted price
      original price ──► 0.68       0.78  ◄── adjusted price
      original price ──► 0.69       0.78  ◄── adjusted price
      original price ──► 0.70       0.78  ◄── adjusted price
      original price ──► 0.71       0.82  ◄── adjusted price
      original price ──► 0.72       0.82  ◄── adjusted price
      original price ──► 0.73       0.82  ◄── adjusted price
      original price ──► 0.74       0.82  ◄── adjusted price
      original price ──► 0.75       0.82  ◄── adjusted price
      original price ──► 0.76       0.86  ◄── adjusted price
      original price ──► 0.77       0.86  ◄── adjusted price
      original price ──► 0.78       0.86  ◄── adjusted price
      original price ──► 0.79       0.86  ◄── adjusted price
      original price ──► 0.80       0.86  ◄── adjusted price
      original price ──► 0.81       0.90  ◄── adjusted price
      original price ──► 0.82       0.90  ◄── adjusted price
      original price ──► 0.83       0.90  ◄── adjusted price
      original price ──► 0.84       0.90  ◄── adjusted price
      original price ──► 0.85       0.90  ◄── adjusted price
      original price ──► 0.86       0.94  ◄── adjusted price
      original price ──► 0.87       0.94  ◄── adjusted price
      original price ──► 0.88       0.94  ◄── adjusted price
      original price ──► 0.89       0.94  ◄── adjusted price
      original price ──► 0.90       0.94  ◄── adjusted price
      original price ──► 0.91       0.98  ◄── adjusted price
      original price ──► 0.92       0.98  ◄── adjusted price
      original price ──► 0.93       0.98  ◄── adjusted price
      original price ──► 0.94       0.98  ◄── adjusted price
      original price ──► 0.95       0.98  ◄── adjusted price
      original price ──► 0.96       1.00  ◄── adjusted price
      original price ──► 0.97       1.00  ◄── adjusted price
      original price ──► 0.98       1.00  ◄── adjusted price
      original price ──► 0.99       1.00  ◄── adjusted price
      original price ──► 1.00       1.00  ◄── adjusted price

version 2

<lang rexx>/* REXX ***************************************************************

  • Inspired by some other solutions tested with version 1 (above)
  • 20.04.2013 Walter Pachl
  • 03.11.2013 -"- move r. computation (once is enough)
                                                                                                                                            • /

rl='0.10 0.18 0.26 0.32 0.38 0.44 0.50 0.54 0.58 0.62',

  '0.66 0.70 0.74 0.78 0.82 0.86 0.90 0.94 0.98 1.00'

Do i=1 To 20

 Parse Var rl r.i rl
 End

Do x=0 To 1 By 0.01

 old=adjprice(x)
 new=adjprice2(x)
 If old<>new Then tag='??'
 else tag=
 Say x old new  tag
 End

Exit

adjprice2: Procedure Expose r.

 i=((100*arg(1)-1)%5+1)
 Return r.i</lang>

Ring

<lang ring> see pricefraction(0.5)

func pricefraction n

    if n < 0.06 return 0.10 ok
    if n < 0.11 return 0.18 ok
    if n < 0.16 return 0.26 ok
    if n < 0.21 return 0.32 ok
    if n < 0.26 return 0.38 ok
    if n < 0.31 return 0.44 ok
    if n < 0.36 return 0.50 ok
    if n < 0.41 return 0.54 ok
    if n < 0.46 return 0.58 ok
    if n < 0.51 return 0.62 ok
    if n < 0.56 return 0.66 ok
    if n < 0.61 return 0.70 ok
    if n < 0.66 return 0.74 ok
    if n < 0.71 return 0.78 ok
    if n < 0.76 return 0.82 ok
    if n < 0.81 return 0.86 ok
    if n < 0.86 return 0.90 ok
    if n < 0.91 return 0.94 ok 
    if n < 0.96 return 0.98 ok
    return 1

</lang>

Ruby

A simple function with hardcoded values. <lang ruby>def rescale_price_fraction(value)

 raise ArgumentError, "value=#{value}, must have: 0 <= value < 1.01" if value < 0 || value >= 1.01
 if     value < 0.06  then  0.10
 elsif  value < 0.11  then  0.18
 elsif  value < 0.16  then  0.26
 elsif  value < 0.21  then  0.32
 elsif  value < 0.26  then  0.38
 elsif  value < 0.31  then  0.44
 elsif  value < 0.36  then  0.50
 elsif  value < 0.41  then  0.54
 elsif  value < 0.46  then  0.58
 elsif  value < 0.51  then  0.62
 elsif  value < 0.56  then  0.66
 elsif  value < 0.61  then  0.70
 elsif  value < 0.66  then  0.74
 elsif  value < 0.71  then  0.78
 elsif  value < 0.76  then  0.82
 elsif  value < 0.81  then  0.86
 elsif  value < 0.86  then  0.90
 elsif  value < 0.91  then  0.94
 elsif  value < 0.96  then  0.98
 elsif  value < 1.01  then  1.00
 end

end</lang>

Or, where we can cut and paste the textual table in one place

Works with: Ruby version 1.8.7+

for the String#lines method.

For Ruby 1.8.6, use String#each_line

<lang ruby>class Price

 ConversionTable = <<-END_OF_TABLE
   >=  0.00  <  0.06  :=  0.10
   >=  0.06  <  0.11  :=  0.18
   >=  0.11  <  0.16  :=  0.26
   >=  0.16  <  0.21  :=  0.32
   >=  0.21  <  0.26  :=  0.38
   >=  0.26  <  0.31  :=  0.44
   >=  0.31  <  0.36  :=  0.50
   >=  0.36  <  0.41  :=  0.54
   >=  0.41  <  0.46  :=  0.58
   >=  0.46  <  0.51  :=  0.62
   >=  0.51  <  0.56  :=  0.66
   >=  0.56  <  0.61  :=  0.70
   >=  0.61  <  0.66  :=  0.74
   >=  0.66  <  0.71  :=  0.78
   >=  0.71  <  0.76  :=  0.82
   >=  0.76  <  0.81  :=  0.86
   >=  0.81  <  0.86  :=  0.90
   >=  0.86  <  0.91  :=  0.94
   >=  0.91  <  0.96  :=  0.98
   >=  0.96  <  1.01  :=  1.00
 END_OF_TABLE
 RE = %r{ ([<>=]+) \s* (\d\.\d\d) \s* ([<>=]+) \s* (\d\.\d\d) \D+ (\d\.\d\d) }x
 # extract the comparison operators and numbers from the table
 CONVERSION_TABLE = ConversionTable.lines.inject([]) do |table, line| 
   m = line.match(RE) 
   if not m.nil? and m.length == 6
     table << [m[1], m[2].to_f, m[3], m[4].to_f, m[5].to_f] 
   end
   table
 end
 MIN_COMP, MIN = CONVERSION_TABLE[0][0..1] 
 MAX_COMP, MAX = CONVERSION_TABLE[-1][2..3]
 def initialize(value)
   if (not value.send(MIN_COMP, MIN)) or (not value.send(MAX_COMP, MAX))
     raise ArgumentError, "value=#{value}, must have: #{MIN} #{MIN_COMP} value #{MAX_COMP} #{MAX}"
   end
   @standard_value = CONVERSION_TABLE.find do |comp1, lower, comp2, upper, standard|
     value.send(comp1, lower) and value.send(comp2, upper)
   end.last
 end
 attr_reader :standard_value

end</lang>

And a test suite <lang ruby>require 'test/unit'

class PriceFractionTests < Test::Unit::TestCase

 @@ok_tests = [
   [0.3793, 0.54],
   [0.4425, 0.58],
   [0.0746, 0.18],
   [0.6918, 0.78],
   [0.2993, 0.44],
   [0.5486, 0.66],
   [0.7848, 0.86],
   [0.9383, 0.98],
   [0.2292, 0.38],
 ]
 @@bad_tests = [1.02, -3]
 def test_ok
   @@ok_tests.each do |val, exp| 
     assert_equal(exp, rescale_price_fraction(val))
     assert_equal(exp, Price.new(val).standard_value)
   end
   @@bad_tests.each do |val| 
     assert_raise(ArgumentError) {rescale_price_fraction(val)}
     assert_raise(ArgumentError) {Price.new(val).standard_value}
   end
 end

end</lang>

Output:
Loaded suite price_fraction
Started
.
Finished in 0.001000 seconds.

1 tests, 22 assertions, 0 failures, 0 errors, 0 skips

Run BASIC

<lang runbasic>data .06, .1,.11,.18,.16,.26,.21,.32,.26,.38,.31,.44,.36,.50,.41,.54,.46,.58,.51,.62 data .56,.66,.61,.70,.66,.74,.71,.78,.76,.82,.81,.86,.86,.90,.91,.94,.96,.98

dim od(100) dim nd(100) for i = 1 to 19 read oldDec read newDec j = j + 1 for j = j to oldDec * 100

  nd(j) = newDec

next j next i

[loop] input "Gimme a number";numb decm = val(using("##",(numb mod 1) * 100)) print numb;" -->";nd(decm)

goto [loop]</lang>

Gimme a number?12.676
12.676 -->0.78
Gimme a number?4.876
4.876 -->0.94
Gimme a number?34.12
34.12 -->0.26

Rust

<lang rust>fn fix_price(num: f64) -> f64 {

   match num {
       0.96...1.00 => 1.00,
       0.91...0.96 => 0.98,
       0.86...0.91 => 0.94,
       0.81...0.86 => 0.90,
       0.76...0.81 => 0.86,
       0.71...0.76 => 0.82,
       0.66...0.71 => 0.78,
       0.61...0.66 => 0.74,
       0.56...0.61 => 0.70,
       0.51...0.56 => 0.66,
       0.46...0.51 => 0.62,
       0.41...0.46 => 0.58,
       0.36...0.41 => 0.54,
       0.31...0.36 => 0.50,
       0.26...0.31 => 0.44,
       0.21...0.26 => 0.38,
       0.16...0.21 => 0.32,
       0.11...0.16 => 0.26,
       0.06...0.11 => 0.18,
       0.00...0.06 => 0.10,
       // panics on invalid value
       _ => unreachable!(),
   }

}

fn main() {

   let mut n: f64 = 0.04;
   while n <= 1.00 {
       println!("{:.2} => {}", n, fix_price(n));
       n += 0.04;
   }

}

// and a unit test to check that we haven't forgotten a branch, use 'cargo test' to execute test. // // typically this could be included in the match as those check for exhaustiveness already // by explicitly listing all remaining ranges / values instead of a catch-all underscore (_) // but f64::NaN, f64::INFINITY and f64::NEG_INFINITY can't be matched like this

  1. [test]

fn exhaustiveness_check() {

   let mut input_price = 0.;
   while input_price <= 1. {
       fix_price(input_price);
       input_price += 0.01;
   }

}</lang>

Output:
0.04 => 0.1
0.09 => 0.18
0.14 => 0.26
0.19 => 0.32
0.24 => 0.38
0.29 => 0.44
0.34 => 0.5
0.39 => 0.54
0.44 => 0.58
0.49 => 0.62
0.54 => 0.66
0.59 => 0.7
0.64 => 0.74
0.69 => 0.78
0.74 => 0.82
0.79 => 0.86
0.84 => 0.9
0.89 => 0.94
0.94 => 0.98
0.99 => 1

Output of unit test:

running 1 test
test exhaustiveness_check ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

Scala

<lang scala>def priceFraction(x:Double)=x match {

  case n if n>=0 && n<0.06 => 0.10
  case n if n<0.11 => 0.18
  case n if n<0.36 => ((((n*100).toInt-11)/5)*6+26)/100.toDouble
  case n if n<0.96 => ((((n*100).toInt-31)/5)*4+50)/100.toDouble
  case _ => 1.00

}

def testPriceFraction()=

  for(n <- 0.00 to (1.00, 0.01)) println("%.2f  %.2f".format(n, priceFraction(n)))</lang>
Output:
0,00  0,10
0,01  0,10
0,02  0,10
0,03  0,10
0,04  0,10
0,05  0,10
0,06  0,18
...
0,25  0,38
0,26  0,44
0,27  0,44
0,28  0,44
0,29  0,44
0,30  0,44
0,31  0,50
0,32  0,50
0,33  0,50
0,34  0,50
0,35  0,50
0,36  0,54
0,37  0,54
...
0,88  0,94
0,89  0,94
0,90  0,94
0,91  0,98
0,92  0,98
0,93  0,98
0,94  0,98
0,95  0,98
0,96  1,00
0,97  1,00
0,98  1,00
0,99  1,00
1,00  1,00

Seed7

<lang seed7>$ include "seed7_05.s7i";

 include "float.s7i";

const func float: computePrice (in float: x) is func

 result
   var float: price is 0.0;
 begin
   if x >= 0.0 and x < 0.06 then
     price := 0.10;
   elsif x < 0.11 then
     price := 0.18;
   elsif x < 0.36 then
     price := flt(((trunc(x * 100.0) - 11) div 5) * 6 + 26) / 100.0;
   elsif x < 0.96 then
     price := flt(((trunc(x * 100.0) - 31) div 5) * 4 + 50) / 100.0;
   else
     price := 1.0;
   end if;
 end func;

const proc: main is func

 local
   var integer: i is 0;
 begin
   for i range 0 to 100 do
     writeln(flt(i) / 100.0 digits 2 <& " " <& computePrice(flt(i) / 100.0) digits 2);
   end for;
 end func;</lang>

The following variant of computePrice works with a table and raises RANGE_ERROR when x < 0.0 or x >= 1.01 holds: <lang seed7>const array array float: table is [] (

   [] (0.06, 0.10), [] (0.11, 0.18), [] (0.16, 0.26), [] (0.21, 0.32), [] (0.26, 0.38),
   [] (0.31, 0.44), [] (0.36, 0.50), [] (0.41, 0.54), [] (0.46, 0.58), [] (0.51, 0.62),
   [] (0.56, 0.66), [] (0.61, 0.70), [] (0.66, 0.74), [] (0.71, 0.78), [] (0.76, 0.82),
   [] (0.81, 0.86), [] (0.86, 0.90), [] (0.91, 0.94), [] (0.96, 0.98), [] (1.01, 1.00));

const func float: computePrice (in float: x) is func

 result
   var float: price is 0.0;
 local
   var integer: index is 1;
 begin
   if x >= 0.0 then
     while x >= table[index][1] do
       incr(index);
     end while;
     price := table[index][2];
   else
     raise RANGE_ERROR;
   end if;
 end func;</lang>

Sidef

<lang ruby>var table = <<'EOT'.lines.map { .words.grep{.is_numeric}.map{.to_n} } >= 0.00 < 0.06  := 0.10 >= 0.06 < 0.11  := 0.18 >= 0.11 < 0.16  := 0.26 >= 0.16 < 0.21  := 0.32 >= 0.21 < 0.26  := 0.38 >= 0.26 < 0.31  := 0.44 >= 0.31 < 0.36  := 0.50 >= 0.36 < 0.41  := 0.54 >= 0.41 < 0.46  := 0.58 >= 0.46 < 0.51  := 0.62 >= 0.51 < 0.56  := 0.66 >= 0.56 < 0.61  := 0.70 >= 0.61 < 0.66  := 0.74 >= 0.66 < 0.71  := 0.78 >= 0.71 < 0.76  := 0.82 >= 0.76 < 0.81  := 0.86 >= 0.81 < 0.86  := 0.90 >= 0.86 < 0.91  := 0.94 >= 0.91 < 0.96  := 0.98 >= 0.96 < 1.01  := 1.00 EOT

func price(money) {

   table.each { |row|
          (row[0] <= money) ->
       && (row[1] >  money) ->
       && return row[2];
   }
   die "Out of range";

}

for n in %n(0.3793 0.4425 0.0746 0.6918 0.2993 0.5486 0.7848 0.9383 0.2292) {

   say price(n);

}</lang>

Output:
0.54
0.58
0.18
0.78
0.44
0.66
0.86
0.98
0.38

Smalltalk

Works with: GNU Smalltalk

<lang smalltalk>"Table driven rescale" Object subclass: PriceRescale [

 |table|
 PriceRescale class  >> new: theTable [
   ^ self basicNew initialize: theTable
 ]
 initialize: theTable [
    table := theTable asOrderedCollection.
    ^self
 ]
 rescale: aPrice [ |v1 v2|
   1 to: (table size - 1) do: [:i|
     v1 := table at: i.
     v2 := table at: (i+1).
     ((aPrice >= (v1 x)) & (aPrice < (v2 x)))
       ifTrue: [ ^ v1 y ]
   ].
   (aPrice < ((v1:=(table first)) x)) ifTrue: [ ^ v1 y ]. 
   (aPrice >= ((v1:=(table last)) x)) ifTrue: [ ^ v1 y ]
 ]

].

|pr| pr := PriceRescale

        new: {  0.00@0.10 .
                0.06@0.18 .
                0.11@0.26 .
                0.16@0.32 .
                0.21@0.38 .
                0.26@0.44 .
                0.31@0.50 .
                0.36@0.54 .
                0.41@0.58 .
                0.46@0.62 .
                0.51@0.66 .
                0.56@0.70 .
                0.61@0.74 .
                0.66@0.78 .
                0.71@0.82 .
                0.76@0.86 .
                0.81@0.90 .
                0.86@0.94 .
                0.91@0.98 .
                0.96@1.00 .
                1.01@1.00
              }.

"get a price" (pr rescale: ( (Random between: 0 and: 100)/100 )) displayNl.</lang>

Swift

<lang swift>let ranges = [

 (0.00..<0.06, 0.10),
 (0.06..<0.11, 0.18),
 (0.11..<0.16, 0.26),
 (0.16..<0.21, 0.32),
 (0.21..<0.26, 0.38),
 (0.26..<0.31, 0.44),
 (0.31..<0.36, 0.50),
 (0.36..<0.41, 0.54),
 (0.41..<0.46, 0.58),
 (0.46..<0.51, 0.62),
 (0.51..<0.56, 0.66),
 (0.56..<0.61, 0.70),
 (0.61..<0.66, 0.74),
 (0.66..<0.71, 0.78),
 (0.71..<0.76, 0.82),
 (0.76..<0.81, 0.86),
 (0.81..<0.86, 0.90),
 (0.86..<0.91, 0.94),
 (0.91..<0.96, 0.98),
 (0.96..<1.01, 1.00)

]

func adjustDouble(_ val: Double, accordingTo ranges: [(Range<Double>, Double)]) -> Double? {

 return ranges.first(where: { $0.0.contains(val) })?.1

}

for val in stride(from: 0.0, through: 1, by: 0.01) {

 let strFmt = { String(format: "%.2f", $0) }
 print("\(strFmt(val)) -> \(strFmt(adjustDouble(val, accordingTo: ranges) ?? val))")

}</lang>

Output:
0.00 -> 0.10
0.01 -> 0.10
0.02 -> 0.10
0.03 -> 0.10
0.04 -> 0.10
0.05 -> 0.10
0.06 -> 0.18
0.07 -> 0.18
0.08 -> 0.18
0.09 -> 0.18
0.10 -> 0.18
0.11 -> 0.26
0.12 -> 0.26
0.13 -> 0.26
0.14 -> 0.26
0.15 -> 0.26
0.16 -> 0.32
0.17 -> 0.32
0.18 -> 0.32
0.19 -> 0.32
0.20 -> 0.32
0.21 -> 0.38
0.22 -> 0.38
0.23 -> 0.38
0.24 -> 0.38
0.25 -> 0.38
0.26 -> 0.44
0.27 -> 0.44
0.28 -> 0.44
0.29 -> 0.44
0.30 -> 0.44
0.31 -> 0.50
0.32 -> 0.50
0.33 -> 0.50
0.34 -> 0.50
0.35 -> 0.50
0.36 -> 0.54
0.37 -> 0.54
0.38 -> 0.54
0.39 -> 0.54
0.40 -> 0.54
0.41 -> 0.58
0.42 -> 0.58
0.43 -> 0.58
0.44 -> 0.58
0.45 -> 0.58
0.46 -> 0.62
0.47 -> 0.62
0.48 -> 0.62
0.49 -> 0.62
0.50 -> 0.62
0.51 -> 0.66
0.52 -> 0.66
0.53 -> 0.66
0.54 -> 0.66
0.55 -> 0.66
0.56 -> 0.70
0.57 -> 0.70
0.58 -> 0.70
0.59 -> 0.70
0.60 -> 0.70
0.61 -> 0.74
0.62 -> 0.74
0.63 -> 0.74
0.64 -> 0.74
0.65 -> 0.74
0.66 -> 0.78
0.67 -> 0.78
0.68 -> 0.78
0.69 -> 0.78
0.70 -> 0.78
0.71 -> 0.82
0.72 -> 0.82
0.73 -> 0.82
0.74 -> 0.82
0.75 -> 0.82
0.76 -> 0.86
0.77 -> 0.86
0.78 -> 0.86
0.79 -> 0.86
0.80 -> 0.86
0.81 -> 0.90
0.82 -> 0.90
0.83 -> 0.90
0.84 -> 0.90
0.85 -> 0.90
0.86 -> 0.94
0.87 -> 0.94
0.88 -> 0.94
0.89 -> 0.94
0.90 -> 0.94
0.91 -> 0.98
0.92 -> 0.98
0.93 -> 0.98
0.94 -> 0.98
0.95 -> 0.98
0.96 -> 1.00
0.97 -> 1.00
0.98 -> 1.00
0.99 -> 1.00
1.00 -> 1.00

Tcl

Structured as two functions, one to parse the input data as described in the problem into a form which Tcl can work with easily, and the other to perform the mapping. <lang tcl># Used once to turn the table into a "nice" form proc parseTable table {

   set map {}
   set LINE_RE {^ *>= *([0-9.]+) *< *([0-9.]+) *:= *([0-9.]+) *$}
   foreach line [split $table \n] {

if {[string trim $line] eq ""} continue if {[regexp $LINE_RE $line -> min max target]} { lappend map $min $max $target } else { error "invalid table format: $line" }

   }
   return $map

}

  1. How to apply the "nice" table to a particular value

proc priceFraction {map value} {

   foreach {minimum maximum target} $map {

if {$value >= $minimum && $value < $maximum} {return $target}

   }
   # Failed to map; return the input
   return $value

}</lang> How it is used: <lang tcl># Make the mapping set inputTable {

   >=  0.00  <  0.06  :=  0.10
   >=  0.06  <  0.11  :=  0.18
   >=  0.11  <  0.16  :=  0.26
   >=  0.16  <  0.21  :=  0.32
   >=  0.21  <  0.26  :=  0.38
   >=  0.26  <  0.31  :=  0.44
   >=  0.31  <  0.36  :=  0.50
   >=  0.36  <  0.41  :=  0.54
   >=  0.41  <  0.46  :=  0.58
   >=  0.46  <  0.51  :=  0.62
   >=  0.51  <  0.56  :=  0.66
   >=  0.56  <  0.61  :=  0.70
   >=  0.61  <  0.66  :=  0.74
   >=  0.66  <  0.71  :=  0.78
   >=  0.71  <  0.76  :=  0.82
   >=  0.76  <  0.81  :=  0.86
   >=  0.81  <  0.86  :=  0.90
   >=  0.86  <  0.91  :=  0.94
   >=  0.91  <  0.96  :=  0.98
   >=  0.96  <  1.01  :=  1.00

} set map [parseTable $inputTable]

  1. Apply the mapping to some inputs (from the Oz example)

foreach example {.7388727 .8593103 .826687 .3444635 .0491907} {

   puts "$example -> [priceFraction $map $example]"

}</lang>

Output:
.7388727 -> 0.82
.8593103 -> 0.90
.826687 -> 0.90
.3444635 -> 0.50
.0491907 -> 0.10

Ursala

<lang Ursala>#import flo

le = <0.06,.11,.16,.21,.26,.31,.36,.41,.46,.51,.56,.61,.66,.71,.76,.81,.86,.91,.96,1.01> out = <0.10,.18,.26,.32,.38,.44,.50,.54,.58,.62,.66,.70,.74,.78,.82,.86,.90,.94,.98,1.>

price_fraction = fleq@rlPlX*|rhr\~&p(le,out)</lang> main points:

  • ~&p(le,out) zips the pair of lists le and out into a list of pairs
  • A function of the form f\y applied to an argument x evaluates to f(x,y)
  • A function of the form f*| applied to a pair (x,y) where y is a list, makes a list of pairs with x on the left of each item and an item of y on the right. Then it applies f to each pair, makes a list of the right sides of those for which f returned true, and makes a separate list of the right sides of those for which f returned false.
  • The suffix rhr after the *| operator extracts the right side of the head of the right list from the result.
  • The operand to the *| operator, fleq@rlPlX is the less-or-equal predicate on floating point numbers, composed with the function ~&rlPlX which transforms a triple (u,(v,w)) to (v,u)

test program: <lang Ursala>#cast %eL

test = price_fraction* <0.34,0.070145,0.06,0.05,0.50214,0.56,1.,0.99,0.> </lang>

Output:
<
   5.000000e-01,
   1.800000e-01,
   1.800000e-01,
   1.000000e-01,
   6.200000e-01,
   7.000000e-01,
   1.000000e+00,
   1.000000e+00,
   1.000000e-01>

VBA

<lang vb> Option Explicit

Sub Main() Dim test, i As Long

   test = Array(0.34, 0.070145, 0.06, 0.05, 0.50214, 0.56, 1#, 0.99, 0#, 0.7388727)
   For i = 0 To UBound(test)
       Debug.Print test(i) & " := " & Price_Fraction(CSng(test(i)))
   Next i

End Sub

Private Function Price_Fraction(n As Single) As Single Dim Vin, Vout, i As Long

   Vin = Array(0.06, 0.11, 0.16, 0.21, 0.26, 0.31, 0.36, 0.41, 0.46, 0.51, 0.56, 0.61, 0.66, 0.71, 0.76, 0.81, 0.86, 0.91, 0.96, 1.01)
   Vout = Array(0.1, 0.18, 0.26, 0.32, 0.38, 0.44, 0.5, 0.54, 0.58, 0.62, 0.66, 0.7, 0.74, 0.78, 0.82, 0.86, 0.9, 0.94, 0.98, 1#)
   For i = 0 To UBound(Vin)
       If n < Vin(i) Then Price_Fraction = Vout(i): Exit For
   Next i

End Function</lang>

Output:
0.34 := 0.5
0.070145 := 0.18
0.06 := 0.18
0.05 := 0.1
0.50214 := 0.62
0.56 := 0.7
1 := 1
0.99 := 1
0 := 0.1
0.7388727 := 0.82

VBScript

<lang vb> Function pf(p)

   If p < 0.06 Then 
       pf = 0.10
   ElseIf p < 0.11 Then 
   	pf = 0.18
   ElseIf p < 0.16 Then 
   	pf = 0.26
   ElseIf p < 0.21 Then 
   	pf = 0.32
   ElseIf p < 0.26 Then 
   	pf = 0.38
   ElseIf p < 0.31 Then 
   	pf = 0.44
   ElseIf p < 0.36 Then 
   	pf = 0.50
   ElseIf p < 0.41 Then 
   	pf = 0.54
   ElseIf p < 0.46 Then 
   	pf = 0.58
   ElseIf p < 0.51 Then 
   	pf = 0.62
   ElseIf p < 0.56 Then 
   	pf = 0.66
   ElseIf p < 0.61 Then 
   	pf = 0.70
   ElseIf p < 0.66 Then 
   	pf = 0.74
   ElseIf p < 0.71 Then 
   	pf = 0.78
   ElseIf p < 0.76 Then 
   	pf = 0.82
   ElseIf p < 0.81 Then 
   	pf = 0.86
   ElseIf p < 0.86 Then 
   	pf = 0.90
   ElseIf p < 0.91 Then 
   	pf = 0.94
   ElseIf p < 0.96 Then 
   	pf = 0.98
   Else 
   	pf = 1.00
   End If

End Function

WScript.Echo pf(0.7388727) WScript.Echo pf(0.8593103) WScript.Echo pf(0.826687) WScript.Echo pf(0.3444635) </lang>

Output:
0.82
0.9
0.9
0.5

Wren

Library: Wren-fmt

<lang ecmascript>import "/fmt" for Fmt

var rescale = Fn.new { |v|

   return (v < 0.06) ? 0.10 :
          (v < 0.11) ? 0.18 :
          (v < 0.16) ? 0.26 :
          (v < 0.21) ? 0.32 :
          (v < 0.26) ? 0.38 :
          (v < 0.31) ? 0.44 :
          (v < 0.36) ? 0.50 :
          (v < 0.41) ? 0.54 :
          (v < 0.46) ? 0.58 :
          (v < 0.51) ? 0.62 :
          (v < 0.56) ? 0.66 :
          (v < 0.61) ? 0.70 :
          (v < 0.66) ? 0.74 :
          (v < 0.71) ? 0.78 :
          (v < 0.76) ? 0.82 :
          (v < 0.81) ? 0.86 :
          (v < 0.86) ? 0.90 :
          (v < 0.91) ? 0.94 :
          (v < 0.96) ? 0.98 : 1.00

}

var tests = [0.49, 0.79, 1.00, 0.83, 0.99, 0.23, 0.12, 0.28, 0.72, 0.37, 0.95, 0.51, 0.43, 0.52, 0.84, 0.89, 0.48, 0.48, 0.30, 0.01] for (test in tests) {

   Fmt.print("$4.2f -> $4.2f", test, rescale.call(test))

}</lang>

Output:
0.49 -> 0.62
0.79 -> 0.86
1.00 -> 1.00
0.83 -> 0.90
0.99 -> 1.00
0.23 -> 0.38
0.12 -> 0.26
0.28 -> 0.44
0.72 -> 0.82
0.37 -> 0.54
0.95 -> 0.98
0.51 -> 0.66
0.43 -> 0.58
0.52 -> 0.66
0.84 -> 0.90
0.89 -> 0.94
0.48 -> 0.62
0.48 -> 0.62
0.30 -> 0.44
0.01 -> 0.10

XPL0

<lang XPL0>include c:\cxpl\codes; \intrinsic 'code' declarations

func real Price(V); \Convert to standard value real V; [V:= V + 0.001; \avoids possible rounding error i.e. 0.059999999 case of

 V < 0.06: ret 0.10;
 V < 0.11: ret 0.18;
 V < 0.16: ret 0.26;
 V < 0.21: ret 0.32;
 V < 0.26: ret 0.38;
 V < 0.31: ret 0.44;
 V < 0.36: ret 0.50;
 V < 0.41: ret 0.54;
 V < 0.46: ret 0.58;
 V < 0.51: ret 0.62;
 V < 0.56: ret 0.66;
 V < 0.61: ret 0.70;
 V < 0.66: ret 0.74;
 V < 0.71: ret 0.78;
 V < 0.76: ret 0.82;
 V < 0.81: ret 0.86;
 V < 0.86: ret 0.90;
 V < 0.91: ret 0.94;
 V < 0.96: ret 0.98

other ret 1.00; ];

[Format(1,2); RlOut(0, Price(0.0599)); CrLf(0); RlOut(0, Price(0.10)); CrLf(0); RlOut(0, Price(1.0)); CrLf(0); ]</lang>

Output:
0.18
0.18
1.00

zkl

<lang zkl>fcn convert(price){ // float --> float

            //   <    -->, increments of 0.05 but tables are easier to update
  var vert=T( T(0.06, 0.10), T(0.11, 0.18), T(0.16, 0.26),

T(0.21, 0.32), T(0.26, 0.38), T(0.31, 0.44), T(0.36, 0.50), T(0.41, 0.54), T(0.46, 0.58), T(0.51, 0.62), T(0.56, 0.66), T(0.61, 0.70), T(0.66, 0.74), T(0.71, 0.78), T(0.76, 0.82), T(0.81, 0.86), T(0.86, 0.90), T(0.91, 0.94), T(0.96, 0.98), T(1.01, 1.00), );

  vert.filter1('wrap([(a,_)]){ price<a })[1] 

}</lang> <lang zkl>fcn convert2(price){ // shifting the fractional part to the integer portion

  var vert=T(0.10, 0.18, 0.26, 0.32, 0.38, 0.44, 0.50, 0.54, 0.58, 0.62, 
             0.66, 0.70, 0.74, 0.78, 0.82, 0.86, 0.90, 0.94, 0.98, 1.00);
   vert[(price*100-1)/005];

}</lang> <lang zkl>T(0.7388727, 0.8593103, 0.826687, 0.3444635, 0.0491907).apply(convert) .println(); T(0.7388727, 0.8593103, 0.826687, 0.3444635, 0.0491907).apply(convert2).println();</lang>

Output:
L(0.82,0.9,0.9,0.5,0.1)
L(0.82,0.9,0.9,0.5,0.1)