# Rounding a double value to x number of decimal places in swift

Can anyone tell me how to round a double value to x number of decimal places in Swift?

I have:

``````var totalWorkTimeInHours = (totalWorkTime/60/60)
``````

With `totalWorkTime` being an NSTimeInterval (double) in second.

`totalWorkTimeInHours` will give me the hours, but it gives me the amount of time in such a long precise number e.g. 1.543240952039......

How do I round this down to, say, 1.543 when I print `totalWorkTimeInHours`?

14

You can use Swift's `round` function to accomplish this.

To round a `Double` with 3 digits precision, first multiply it by 1000, round it and divide the rounded result by 1000:

``````let x = 1.23556789
let y = Double(round(1000*x)/1000)
print(y)  // 1.236
``````

Other than any kind of `printf(...)` or `String(format: ...)` solutions, the result of this operation is still of type `Double`.

EDIT:

What Every Programmer Should Know About Floating-Point Arithmetic

Tuesday, June 1, 2021

35

Use "Nx" for x decimal digits.

`````` public void DisplayNDecimal(double dbValue, int nDecimal)
{
Console.WriteLine(dbValue.ToString("N" + nDecimal));
}
``````
Saturday, June 19, 2021

59

Taking on board what you said I have modified my code slightly to cover different locales. The key was taking a value string in a localised format to a Double that is rounded based on the format string.

The format string is always a UK based format with the decimal seperators specified as "." and thousand seperators specified as ",".

I am using the DecimalFormat to initially parse the localised format based on a specified locale. This gives a Double equivalent of the string correctly. I then use a BigDecimal to handle the rounding. I can get the number of decimal places from the DecimalFormat instance and call setScale on the BigDecimal to perform the rounding.

The initial code structure has been modified to allow you to see what happens under different locale circumstances thanks @RD01 for noting importance of other locales.

I now have code as follows:

``````private void runTests3() {
// output current locale we are running under
System.out.println( "Current Locale is " + Locale.getDefault().toString() );

// number in Central European Format with a format string specified in UK format
String numbersInEuropeanFormatString[] = new String[] { "1.000,234567", "1,2345678", "1.222.333,234567" };
String formatUK = "###,##0.0000";

// output numbers using the german locale
System.out.println("Output numbers using the German localen");
for(String num : numbersInEuropeanFormatString ) {
formatNumberAsDouble(num, formatUK, Locale.GERMAN);
}

// output numbers using the UK locale.
// this should return unexpected results as the number is in European format
System.out.println("Output numbers using the UK localen");
for(String num : numbersInEuropeanFormatString ) {
formatNumberAsDouble(num, formatUK, Locale.UK);
}

// output numbers using new DecimalFormat( formatUK ) - no locale specified
System.out.println("nnOutput numbers using new DecimalFormat( " + formatUK + " )n");
for(String num : numbersInEuropeanFormatString ) {
formatNumberAsDouble( num, formatUK, null);
}
}

private void formatNumberAsDouble(String value, String format, Locale locale) {

NumberFormat formatter;
int decimalPlaces;

// create the formatter based on the specified locale
if( locale != null ) {
formatter = NumberFormat.getNumberInstance(locale);
// creating the above number format does not take in the format string
// so create a new one that we won't use at all just to get the
// decimal places in it
decimalPlaces = (new DecimalFormat(format)).getMaximumFractionDigits();
} else {
formatter = new DecimalFormat( format );
decimalPlaces = formatter.getMaximumFractionDigits();
}

// get the result as number
Double result = null;
try {
result = formatter.parse( value ).doubleValue();
} catch( ParseException ex ) {
// not bothered at minute
}

// round the Double to the precision specified in the format string

BigDecimal bd = new BigDecimal(result );
Double roundedValue = bd.setScale( decimalPlaces, RoundingMode.HALF_UP ).doubleValue();

// output summary
System.out.println("tValue = " + value);
System.out.println( locale == null  ? "tLocale not specified" : "tLocale = " + locale.toString());
System.out.println( format == null || format.length() == 0 ? "tFormat = Not specified" : "tFormat = " + format);
System.out.println("tResult (Double) = " + result);
System.out.println("tRounded Result (Double) (" + decimalPlaces + "dp) = " + roundedValue);
System.out.println("");
}
``````

This produces the following output:

``````Current Locale is nl_BE
Output numbers using the German locale

Value = 1.000,234567
Locale = de
Format = ###,##0.0000
Result (Double) = 1000.234567
Rounded Result (Double) (4dp) = 1000.2346

Value = 1,2345678
Locale = de
Format = ###,##0.0000
Result (Double) = 1.2345678
Rounded Result (Double) (4dp) = 1.2346

Value = 1.222.333,234567
Locale = de
Format = ###,##0.0000
Result (Double) = 1222333.234567
Rounded Result (Double) (4dp) = 1222333.2346

Output numbers using the UK locale

Value = 1.000,234567
Locale = en_GB
Format = ###,##0.0000
Result (Double) = 1.0
Rounded Result (Double) (4dp) = 1.0

Value = 1,2345678
Locale = en_GB
Format = ###,##0.0000
Result (Double) = 1.2345678E7
Rounded Result (Double) (4dp) = 1.2345678E7

Value = 1.222.333,234567
Locale = en_GB
Format = ###,##0.0000
Result (Double) = 1.222
Rounded Result (Double) (4dp) = 1.222

Output numbers using new DecimalFormat( ###,##0.0000 )

Value = 1.000,234567
Locale not specified
Format = ###,##0.0000
Result (Double) = 1000.234567
Rounded Result (Double) (4dp) = 1000.2346

Value = 1,2345678
Locale not specified
Format = ###,##0.0000
Result (Double) = 1.2345678
Rounded Result (Double) (4dp) = 1.2346

Value = 1.222.333,234567
Locale not specified
Format = ###,##0.0000
Result (Double) = 1222333.234567
Rounded Result (Double) (4dp) = 1222333.2346
``````
Thursday, July 29, 2021

83

Remove the `NavigationView` from `SecondView`.

The `NavigationLink` puts the second view inside the first views navigations view, so you do not need to put it inside a second one.

You can still update the title of the view from `SecondView` like so:

``````struct SecondView: View {
var body: some View {
Text("My View")
}
}
``````
Sunday, September 26, 2021

91

update: Xcode 8.3.2 • Swift 3.1

``````extension Collection where Iterator.Element == String {
var doubleArray: [Double] {
return flatMap{ Double(\$0) }
}
var floatArray: [Float] {
return flatMap{ Float(\$0) }
}
}
``````

usage:

``````let strNumbersArray = ["1.5","2.3","3.7","4.5"]   // ["1.5", "2.3", "3.7", "4.5"]
let doublesArray = strNumbersArray.doubleArray    // [1.5, 2.3, 3.7, 4.5]
let floatsArray = strNumbersArray.floatArray      // [1.5, 2.3, 3.7, 4.5]
let total = doublesArray.reduce(0, +)     // 12
let average = total / Double(doublesArray.count)  // 3
``````

If you have an Array of Any? where you need to convert all strings from Optional Any to Double:

``````extension Collection where Iterator.Element == Any? {
var doubleArrayFromStrings: [Double] {
return flatMap{ Double(\$0 as? String ?? "") }
}
var floatArrayFromStrings: [Float] {
return flatMap{ Float(\$0 as? String ?? "") }
}
}
``````

usage:

``````let strNumbersArray:[Any?] = ["1.5","2.3","3.7","4.5", nil]   // [{Some "1.5"}, {Some "2.3"}, {Some "3.7"}, {Some "4.5"}, nil]
let doublesArray = strNumbersArray.doubleArrayFromStrings    // [1.5, 2.3, 3.7, 4.5]
let floatsArray = strNumbersArray.floatArrayFromStrings      // [1.5, 2.3, 3.7, 4.5]
let total = doublesArray.reduce(0, +)     // 12
let average = total / Double(doublesArray.count)  // 3
``````
Sunday, October 17, 2021