Swift Round up / Max the NSDecimalNumber - swift

Let's say we have an NSDecimal constant called total and it contains the value of 3.33333333 divided by 10/3. 10 and 3 are both NSDecimalNumber.
We want the total to be 4 as an NSDecimalNumber in Swift.
let total = ten/three
// the ideal total would be rounded up whenever there is a floating
in the doc. we have
func NSDecimalRound(_ result: UnsafeMutablePointer<NSDecimal>,
_ number: UnsafePointer<NSDecimal>,
_ scale: Int,
_ roundingMode: NSRoundingMode)
maximumDecimalNumber()
Which one is the best fit for calculator with currency style? Please include an example each how to use them if you know so. Thank you .

let x = NSDecimalNumber(string:"10")
let y = NSDecimalNumber(string:"3")
let total = x.decimalNumberByDividingBy(y).decimalNumberByRoundingAccordingToBehavior( NSDecimalNumberHandler(roundingMode: NSRoundingMode.RoundUp, scale: 0, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)) // 4

Related

Correct way formatting digits into "X.XX" amount

I have a requirement to turn keyboard digits input into amount as cents, for example:
Typing 1 will output 0.01
Typing 10 will output 0.10
Typing 123 will output 1.23
Typing 12345 will output 123.45
My current solution involves multiplying by 0.01 and looking at the reminder:
// split into whole and reminder
let mod = modf(doubleAmount * 0.01)
// define a rounding behavior
let behavior = NSDecimalNumberHandler(roundingMode: .plain,
scale: Int16(places),
raiseOnExactness: false,
raiseOnOverflow: false,
raiseOnUnderflow: false,
raiseOnDivideByZero: true)
let whole = mod.0
let reminder = NSDecimalNumber(value: mod.1).rounding(accordingToBehavior: behavior)
// formatting...
let newnumber = NSNumber(value: whole + reminder.doubleValue)
This will work correct for most values but will break format when working with whole numbers like 10, 100, 1000 etc... The format will then be 0.1, 1.0, 10.0 while I need them to appear as 0.10, 1.00, 10.00 etc...
what is the best/correct way to achieve this?
The NumberFormatter type has a multiplier attribute that can be used for this scenario and then no further calculations will be needed
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
formatter.multiplier = 0.01

Rounding Numbers to Two Significant Figures

I am sure this is an easy question to any of you are experienced in Swift, however, I just started learning how to program and have no idea where to start. What I am trying to do is a round a number to the nearest whole value, or to the third number. This is what I mean:
12.6 //Want rounded to 13
126 //Want rounded to 130
1264 //Want rounded to 1300
I know swift has a .rounded() function, and I have managed to use it to round the nearest 10th, 100th, etc., however, I cannot round the way I would like to. Any advice would be much appreciated.
Here's one way to round any Double or Int (including negative numbers) to a given number of significant figures:
func round(_ num: Double, to places: Int) -> Double {
let p = log10(abs(num))
let f = pow(10, p.rounded() - Double(places) + 1)
let rnum = (num / f).rounded() * f
return rnum
}
func round(_ num: Int, to places: Int) -> Int {
let p = log10(abs(Double(num)))
let f = pow(10, p.rounded() - Double(places) + 1)
let rnum = (Double(num) / f).rounded() * f
return Int(rnum)
}
print(round(0.265, to: 2))
print(round(1.26, to: 2))
print(round(12.6, to: 2))
print(round(126, to: 2))
print(round(1264, to: 2))
Output:
0.27
1.3
13.0
130
1300
As stated by Sulthan you can use NumberFormatter:
let formatter = NumberFormatter()
formatter.usesSignificantDigits = true
formatter.maximumSignificantDigits = 2
formatter.minimumSignificantDigits = 2
if let result = formatter.string(from: 12.6) {
print(result) // prints 13
}
One possibility to implement a rounding algorithm. I suppose you always want the result to be integer.
func round(_ number: Float, to digits: Int) -> Float {
guard number >= 0 else {
return -round(-number, to: digits)
}
let max = pow(10, Float(digits))
var numZeros = 0
var value = number
while (value >= max) {
value /= 10
numZeros += 1
}
return round(value) * pow(10, Float(numZeros))
}
print(round(12.6, to: 2)) // 13
print(round(126, to: 2)) // 130
print(round(1264, to: 2)) // 1300

Convert pounds to pound decimals in Swift (2.2)

How can I convert pounds to pound decimals?
For instance if the user enters 1.8 lbs, I would like to be able to convert it to 1.5 lbs so I can do some calculations.
The code below has two issues.
1- It only works when the user enters less then 10 (e.g 1.9) ounces since I'm multiplying the ounces by 10.
2- It only returns the decimal ounces, It does not return the whole number (pounds).
func poundsToDecimals(pounds:Double)->Double{
let ounces = Double(pounds % 1)
let decimals = ounces / 16 * 10
return decimals
}
print(poundsToDecimals(1.4)) //prints... 0.25
To solve your first problem try converting it the number into a String and then split it up like so:
func poundsToDecimals(pounds: Double) -> Double {
let numberAsString = String(pounds)
var numbers = numberAsString.components(separatedBy: ["."])
let seperatedPounds = Double(numbers[0])!
let ounces = Double(numbers[1])!
let decimals = ounces / 16 * 10
return decimals
}
Can you please specify your second problem further. if you want to return more then one value you usally do it like this.
func poundsToDecimals(pounds: Double) -> (Double, Double) {
let numberAsString = String(pounds)
var numbers = numberAsString.components(separatedBy: ["."])
let seperatedPounds = Double(numbers[0])!
let ounces = Double(numbers[1])!
let decimals = ounces / 16 * 10
return (decimals, seperatedPounds)
}
Hope that helps

Swift Remainder operator precision

I need to round stocks, indices and futures prices to the nearest tick. The first step is to look if the price is a multiple of the tick. Apple docs says "Unlike the remainder operator in C and Objective-C, Swift’s remainder operator can also operate on floating-point numbers".
If I write the following code in a playground or in a console app and I run it, I expect 0 as result but I get a remainder value equals to 0.00999999999999775:
var stringPrice = "17.66"
var price = Double(stringPrice)
var tickSize: Double = 0.01
let remainder = price! % ticksize
This problem breaks my rounding function when using values such 17.66 as aPrice and 0.01 as aTickSize:
func roundPriceToNearestTick(Price aPrice: Double, TickSize a TickSize: Double)-> Double{
let remainder = aPrice % aTickSize
let shouldRoundUp = remainder >= aTickSize/2 ? true : false
let multiple = floor(aPrice/aTickSize)
let returnPrice = !shouldRoundUp ? aTickSize*multiple : aTickSize*multiple + aTickSize
return returnPrice
}
What is the best way to fix this?
Following the comments about the broken floating point math and the need to avoid floats and doubles for all the operations concerning money I changed my code to perform the remainder operation using NSDecimalNumbers. This seems to solve the precision problem.
var stringPrice = "17.66"
var tickSizeDouble : Double = 0.01
var tickSizeDecimalNumber: NSDecimalNumber = 0.01
func decimalNumberRemainder(Dividend aDividend: NSDecimalNumber, Divisor aDivisor: NSDecimalNumber)->NSDecimalNumber{
let behaviour = NSDecimalNumberHandler(roundingMode: NSRoundingMode.RoundDown,
scale: 0,
raiseOnExactness: false ,
raiseOnOverflow: false,
raiseOnUnderflow: false,
raiseOnDivideByZero: false )
let quotient = aDividend.decimalNumberByDividingBy(aDivisor, withBehavior: behaviour)
let subtractAmount = quotient.decimalNumberByMultiplyingBy(aDivisor)
let remainder = aDividend.decimalNumberBySubtracting(subtractAmount)
return remainder
}
let doubleRemainder = Double(stringPrice)! % tickSizeDouble
let decimalRemainder = decimalNumberRemainder(Dividend: NSDecimalNumber(string: stringPrice), Divisor:tickSizeDecimalNumber)
print("Using Double: \(doubleRemainder)")
print("Using NSDecimalNumber: \(decimalRemainder)")

Generating random values in Swift between two integer values

I'm trying to generate random values between two integers. I've tried this, which starts from 0,
let randomNumber = arc4random_uniform(10)
println(randomNumber)
But I need a value between 10 and 50.
try this
let randomNumber = arc4random_uniform(40) + 10
println(randomNumber)
in general form
let lower : UInt32 = 10
let upper : UInt32 = 50
let randomNumber = arc4random_uniform(upper - lower) + lower
println(randomNumber)
This is an option for Swift 4.2 and above using the random() method, which makes it easy!
let randomInt = Int.random(in: 10...50)
The range can be a closed (a...b) or half open (a..<b) range.
If you want a reusable function with simple parameters:
func generateRandomNumber(min: Int, max: Int) -> Int {
let randomNum = Int(arc4random_uniform(UInt32(max) - UInt32(min)) + UInt32(min))
return randomNum
}
more simple way of random number generator
func random(min: Int, max: Int) -> Int {
return Int(arc4random_uniform(UInt32(max - min + 1))) + min
}