DEV Community

Daily Challenge #49 - Dollars and Cents

dev.to staff on August 26, 2019

Today's challenge requires you to create a function that will take a float and return the amount formatted in dollars and cents. For example: 6.2...
Collapse
 
ynndvn profile image
La blatte • Edited

Here we go!

f=a=>`$${a.toFixed`2`}`;

And the results:

f(.4); // "$0.40"
f(0); // "$0.00"
f(6.2); // "$6.20"

And how about some Intl?

f=a=>new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(a)

Which does a bit more, like adding commas:

f(.4); // "$0.40"
f(0); // "$0.00"
f(6.2); // "$6.20"
f(100000000.1234); // "$100,000,000.12"
Collapse
 
hellotusharkhanna profile image
Tushar Khanna • Edited

Hello, I am surprised, you can call a function with ``. How come is it working?

Collapse
 
ynndvn profile image
La blatte

ES6 added this functionality, called Tagged Template! A few examples can be found here: wesbos.com/tagged-template-literals/

Thread Thread
 
hellotusharkhanna profile image
Tushar Khanna

Thanks a ton :) learnt new thing

Collapse
 
mkrl profile image
Mikhail Korolev • Edited

Sometimes I just think about Rails method that does a very specific thing, type it out in console and it works

number_to_currency(number)
Collapse
 
jasman7799 profile image
Jarod Smith
const formatDollars = money => `$${money.toFixed(2)}`;


`
love js

Collapse
 
saschalalala profile image
Sascha • Edited

Mind rounding "errors":

formatDollars(.126)
> '$0.13'

Same happens in python:

print(f"{123.126:.2f}")
123.13
Collapse
 
thepeoplesbourgeois profile image
Josh

It rounded up, though, so is that an error? It seems like expected behavior to me.

Collapse
 
dak425 profile image
Donald Feury • Edited

Go - with tests as usual

fun fact - this was the first time I wrote anything using Vim

dollars.go

package dollars

import (
    "fmt"
)

// Dollars returns the string representation of a float as a dollar amount
func Dollars(amount float64) string {
    return fmt.Sprintf("$%.2f", amount)
}

dollars_test.go

package dollars

import (
    "testing"
)

var testCases = []struct {
    description string
    input       float64
    expected    string
}{
    {
        "only cents",
        .04,
        "$0.04",
    },
    {
        "only dollars",
        3,
        "$3.00",
    },
    {
        "cents & dollars",
        3.14,
        "$3.14",
    },
    {
        "amounts with more than two decimal places round to the nearest cent",
        4.478,
        "$4.48",
    },

}

func TestDollars(t *testing.T) {
    for _, test := range testCases {
        if result := Dollars(test.input); result != test.expected {
            t.Fatalf("FAILED: %s - Dollars(%f): %s, expected %s \n", test.description, test.input, result, test.expected)
        }
        t.Logf("PASS: %s \n", test.description)
    }
}

Collapse
 
tiash990 profile image
Tiash

I'm not sure, but I think that "Sprintf" rounds to nearest integer.
Try with a value like 3.149 if still returns 3.14 or 3.15

Collapse
 
dak425 profile image
Donald Feury

Added additional test case to clarify current rounding behavior.

Collapse
 
dak425 profile image
Donald Feury • Edited

Yeah it rounds to the nearest cent in this case, the question becomes then do we want it to work that way, or do we say "Hey you don't have a full cent" so it always rounds down?

Collapse
 
alfredosalzillo profile image
Alfredo Salzillo

With miles separator too:

const formatMoney = money => [...`$${money .toFixed(2)}`]
  .reverse()
  .flatMap((c, i) => (c != '.' && c != '$' && i > 3 && i % 3 == 0) ? [',', c]: [c])
  .reverse()
  .join('');

// formatMoney(12123123123131232.000) => $12,123,123,123,131,232.00
Collapse
 
peter279k profile image
peter279k

Here is the simple solution with PHP:

function format_money(float $amount): string {
    $amounts = explode('.', (string)$amount);
    $moneyFormat = '$%d.%s';

    if (count($amounts) === 1) {
        $floating = '00';

        return sprintf($moneyFormat, $amounts[0], $floating);
    }

    if (strlen($amounts[1]) === 1) {
      $floating = $amounts[1] . '0';

      return sprintf($moneyFormat, $amounts[0], $floating);
    }

    return sprintf($moneyFormat, $amounts[0], substr($amounts[1], 0, 2));
}
Collapse
 
aminnairi profile image
Amin

My take at the challenge written in Haskell.

toFloat :: String -> Float
toFloat string = read string :: Float

decimalToInt :: Float -> Int
decimalToInt float =
  round
    $ (*) 100
    $ toFloat
    $ take 5
    $ show
    $ float - (fromIntegral $ floor float)

decimalToDollar :: Float -> String
decimalToDollar float =
  "$" 
    ++ (show $ round float)
    ++ "."
    ++ (show $ decimalToInt float)

main :: IO ()
main = do
  putStrLn $ show $ decimalToDollar 6.2 -- "$6.20"
  putStrLn $ show $ decimalToDollar 6.227 -- "$6.23"

Try it online.

For some reason, I get imprecise floating point numbers when grabbing the decimal part of a floating point number in Haskell. I'm pretty new to this language so I must miss something. Feel free to improve my work here.

Collapse
 
jay profile image
Jay

Rust Function:

fn format_dollar(price: f32) -> String {
    format!("${:.2}", price)
}
Collapse
 
ddavisgraphics profile image
David J. Davis • Edited
define_method(:us_curr) { |float| format('$%.2f', float.truncate(2)) }
us_curr 2.1256 # => "$2.12"

I thought about this problem from a financial standpoint and didn't like the default ruby or rails options that have been given so far because of how much lost revenue could be happening. Amazon for example has over a billion transactions a day (according to the first link on google). If we use 1.3 billion transactions and assume that the average fractional cents that they give up in a day of transactions is half a cent (.05). That would cost them 6.5 million dollars in lost revenue from giving up fractions of a cent. My solution just trims the number instead of rounding it.

I could see potential for wanting to round up from a business standpoint too, if the calculations are creating a price point for your product in a currency form then by all means you want to round up to still avoid that 6.5 million hit. In which case you would have to adjust the currency function.

This problem can really get interesting depending on your outlook.

Collapse
 
rafaacioly profile image
Rafael Acioly

Python :)

def to_currency(value: float) -> str:
    return "${:.2f}".format(value)

print(to_currency(6.2)) # $6.20
Collapse
 
matrossuch profile image
Mat-R-Such

Python

print('$%.2f' %(float(input('Give me money '))))
Collapse
 
webcoderph profile image
Maynard Cabalitan • Edited

Ruby

def maney(amount)
  "$" + '%.2f' % amount.to_f
end
Collapse
 
brightone profile image
Oleksii Filonenko

Elixir:

defmodule Day49 do
  def float_to_money(float),
    do: "$#{:io_lib.format("~.2f", [float])}"
end
Collapse
 
hanachin profile image
Seiei Miyagi

ruby <3

define_method(:format_dollar, &"$%.02f".:%)
Collapse
 
brightone profile image
Oleksii Filonenko

Rust:

fn format_dollars(amount: f64) -> String {
    format!("${:.2}", amount)
}
Collapse
 
srisrinu profile image
SRINU • Edited

Here is the python code

num=float(input())
print("${:,.2f}".format(num))