# Rounding numbers (up/down) to nearest multiple and power

**URL:** <https://forums.swift.org/t/rounding-numbers-up-down-to-nearest-multiple-and-power/15547>\
**Category:** Using Swift\
**Created:** [August 27, 2018, 10:29am UTC](https://forums.swift.org/t/rounding-numbers-up-down-to-nearest-multiple-and-power/15547 "2018-08-27T10:29:53Z")\
**Posts on this page:** 1\
**Showing post:** 6

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [August 28, 2018, 12:52pm UTC](https://forums.swift.org/t/rounding-numbers-up-down-to-nearest-multiple-and-power/15547/6 "2018-08-28T12:52:09Z")

</div>

Another attempt, still not entirely sure if everything works correctly:

```swift
extension FixedWidthInteger {

    func roundedTowardZero(toMultipleOf m: Self) -> Self {
        return self - (self % m)
    }

    func roundedAwayFromZero(toMultipleOf m: Self) -> Self {
        let x = self.roundedTowardZero(toMultipleOf: m)
        if x == self { return x }
        return (m.signum() == self.signum()) ? (x + m) : (x - m)
    }
    
    func roundedDown(toMultipleOf m: Self) -> Self {
        return self < 0
            ? self.roundedAwayFromZero(toMultipleOf: m)
            : self.roundedTowardZero(toMultipleOf: m)
    }
    
    func roundedUp(toMultipleOf m: Self) -> Self {
        return self >= 0
            ? self.roundedAwayFromZero(toMultipleOf: m)
            : self.roundedTowardZero(toMultipleOf: m)
    }

    func roundedUpToPowerOfTwo() -> Self {
        precondition(self > 0)
        let shifts = bitWidth &- leadingZeroBitCount
        return nonzeroBitCount == 1 ? self : 1 &<< shifts
    }
}

extension BinaryFloatingPoint {

    func roundedToNearest(multipleOf m: Self) -> Self {
        return self - self.remainder(dividingBy: m)
    }

    func roundedTowardZero(toMultipleOf m: Self) -> Self {
        return self - self.truncatingRemainder(dividingBy: m)
    }

    func roundedAwayFromZero(toMultipleOf m: Self) -> Self {
        let x = self.roundedTowardZero(toMultipleOf: m)
        if self == x {
            return self
        } else {
            return self >= 0 ? x + m : x - m
        }
    }

    func roundedDown(toMultipleOf m: Self) -> Self {
        return self < 0
            ? self.roundedAwayFromZero(toMultipleOf: m)
            : self.roundedTowardZero(toMultipleOf: m)
    }

    func roundedUp(toMultipleOf m: Self) -> Self {
        return self >= 0
            ? self.roundedAwayFromZero(toMultipleOf: m)
            : self.roundedTowardZero(toMultipleOf: m)
    }
}

```

Note for example that:

```swift
print(Float(1.5).roundedToNearest(multipleOf: 1.0)) // 2.0
print(Float(2.5).roundedToNearest(multipleOf: 1.0)) // 2.0 (we might have expected 3.0)

```

This is because `roundedToNearest(multipleOf:)` uses `remainder(dividingBy:)` which has the following property:

> For two finite values x and y, the remainder r of dividing x by y satisfies x == y \* q + r, where q is the integer nearest to x / y. **If x / y is exactly halfway between two integers, q is chosen to be even**.

So:

```swift
print(Float(1.5).remainder(dividingBy: 1.0)) // -0.5
print(Float(2.5).remainder(dividingBy: 1.0)) // 0.5

```

An alternative implementation of `roundedToNearest(multipleOf:)` could perhaps be:

```swift
    func roundedToNearest(multipleOf m: Self) -> Self {
        let x = self >= 0 ? self + m/2 : self - m/2
        return x - x.truncatingRemainder(dividingBy: m)
    }

```

And since these two implementations corresponds to the two rounding rules `.toNearestOrEven` and `.toNearestOrAwayFromZero` we can implement all variants as this single method:

```swift
extension BinaryFloatingPoint {

    func rounded(_ roundingRule: FloatingPointRoundingRule,
                 toMultipleOf m: Self) -> Self
    {
        switch roundingRule {
        case .toNearestOrEven:
            return self - self.remainder(dividingBy: m)
        case .toNearestOrAwayFromZero:
            let x = self >= 0 ? self + m/2 : self - m/2
            return x - x.truncatingRemainder(dividingBy: m)
        case .awayFromZero:
            let x = self.rounded(.towardZero, toMultipleOf: m)
            if self == x {
                return self
            } else {
                return self >= 0 ? x + m : x - m
            }
        case .towardZero:
            return self - self.truncatingRemainder(dividingBy: m)
        case .down:
            return self < 0
                ? self.rounded(.awayFromZero, toMultipleOf: m)
                : self.rounded(.towardZero, toMultipleOf: m)
        case .up:
            return self >= 0
                ? self.rounded(.awayFromZero, toMultipleOf: m)
                : self.rounded(.towardZero, toMultipleOf: m)
        }
    }
    
}

```

Though perhaps the "even" in `.toNearestOrEven` doesn't quite make sense in the context of this method.

---

_[View the full topic](https://forums.swift.org/t/rounding-numbers-up-down-to-nearest-multiple-and-power/15547)._
