Why does swift conversion work for floating point division? - swift

Like in many languages, Swift's division operator defaults to integer division, so:
let n = 1 / 2
print(n) // 0
If you want floating point division, you have to do
let n1 = 1.0 / 2
let n2 = 1 / 2.0
let n3 = Double(1) / 2
let n4 = 1 / Double(2)
print(n1) // 0.5
print(n2) // 0.5
print(n3) // 0.5
print(n4) // 0.5
Again, like most other languages, you can't cast the whole operation:
let n5 = Double(1 / 2)
print(n5) // 0.0
Which happens because swift performs the integer division of 1 and 2 (1 / 2) and gets 0, which it then tries to cast to a Double, effectively giving you 0.0.
I am curious as to why the following works:
let n6 = (1 / 2) as Double
print(n6) // 0.5
I feel like this should produce the same results as Double(1 / 2). Why doesn't it?

1 and 2 are literals. They have no type unless you give them a type from context.
let n6 = (1 / 2) as Double
is essentially the same as
let n6: Double = 1 / 2
that means, you tell the compiler that the result is a Double. That means the compiler searches for operator / with a Double result, and that means it will find the operator / on two Double operands and therefore considers both literals as of type Double.
On the other hand,
let n5 = Double(1 / 2)
is a cast (or better said, initialization of a Double). That means the expression 1 / 2 gets evaluated first and then converted to Double.

Related

Swift unreliable round() method to 2 decimal places

I'm trying to calculate the time between two doubles (distance, speed) to 2 decimal places using swift round() method but there are instances where its unreliable and I end up with something like 58.000000001. I tried to hack fix this by rounding again but even that doesn't work on larger numbers eg 734.00000001 Is there a way to fix this or another way to calculate time between two doubles?
var totalTime: Double = 0
for 0...100 {
let calcTime = 35.3 / 70
let roundedTime = round(calcTime * 100) / 100.0
print("TIME === \(roundedTime)")
totalTime += round(totalTime * 100) / 100 + roundedTime // round again to clamp the extra zero's
print("Total time \(totalTime)")
}

Algorithm to Derive All Possible Math Expressions In a Set To get a Target Value

I am new to Swift Programming, and while I could figure the rest of this out for this app I have floating in my head, I'm having a hard time figuring out how to derive a algorithm that could handle this problem:
Given a set of 4 values (probably best to use Double because some can even be fractions), derive all possible combinations that return a result of a target value--in my case, 24.
For example, a+b+c+d, a+b+d+c, a+d+b+c, d+a+b+c, and all arrangements of that set, plus all possible mathematical operators such as (a*b)^(c-d) or (a+b+c)/d.
I was able to find this article, but it doesn't quite match what I'm looking for, especially as order doesn't matter for me
Number of ways to sum the items in a set to get a target value - Order matters
so for example, I could manually do each combination this way:
if a + b + c + d == 24 {
print("\a + \b + \c + \d")
}
My goal is for the user to enter 4 values and let IOS generate a list of all possible mathematical expressions that result in 24.
Patrick
Here is one approach. Start with an array of expressions and an array of values. Initially, the expressions is just the String value of the values:
let expressions = ["1", "2", "3", "4"]
let values = [1, 2, 3, 4]
Pick two expressions (for example "1" and "2", and a binary operator ("+"), and combine them creating an expressions and values with 3 values:
expressions = ["3", "4", "(1 + 2)"]
values = [3, 4, 3]
Repeat this process combining again two of the expressions with an operation:
expressions = ["3", "(4 + (1 + 2))"]
values = [3, 7]
Finally, combine the last two expressions with "+":
expressions = ["(3 + (4 + (1 + 2)))"]
values = [10]
Once you reach a single expression, check to see if the value matches your target.
The following is a recursive function that tries all combinations of values and operations to create the expressions in search of a target:
import Foundation
// An array of tuples containing an operator name and a closure
// that performs the operation
let ops: [(name: String, function: (Double, Double) -> Double)] = [
("+", { $0 + $1 }),
("-", { $0 - $1 }),
("*", { $0 * $1 }),
("/", { $0 / $1 }),
("^", { pow($0, $1) })
]
func compute(expressions: [String], values: [Double], target: Double) {
// base case of the recursion: if there is only one
// expression and one value, check if the value is the
// target value we're looking for and print the expression
// and value if the target is matched
if expressions.count == 1 {
if values[0] == target {
print("\(expressions[0]) = \(values[0])")
}
} else if expressions.count >= 2 {
// loop through all of the expressions choosing each
// as the first expression
for idx1 in expressions.indices {
// copy the expressions and values arrays so that
// we can remove the expression and value
// without modifying the original arrays
// which will be needed for the next try
var expcopy = expressions
var valcopy = values
let exp1 = expcopy.remove(at: idx1)
let val1 = valcopy.remove(at: idx1)
// loop through the remaining expressions to find
// the second one
for idx2 in expcopy.indices {
// again, copy the arrays to keep from modifying
// the originals while searching
var expcopy2 = expcopy
var valcopy2 = valcopy
let exp2 = expcopy2.remove(at: idx2)
let val2 = valcopy2.remove(at: idx2)
// now try all possible operations to combine
// the two expressions
for op in ops {
// use the closure to compute the value
let value = op.function(val1, val2)
// combine the expressions into a new string
// expression with the operator in the
// middle and surrounded by () if this is
// not the top level expression
var exp = "\(exp1) \(op.name) \(exp2)"
if !expcopy2.isEmpty {
exp = "(\(exp))"
}
// now that we've reduced the number of
// expressions by 1, recurse by calling
// compute again on the reduced list of
// expressions
compute(expressions: expcopy2 + [exp], values: valcopy2 + [value], target: target)
}
}
}
}
}
// This helper function creates the array of expressions from
// the array of values, and then calls the main function above
// to do the real work
func search(values: [Double], target: Double) {
compute(expressions: values.map { String($0) }, values: values, target: target)
}
Example 1:
search(values: [1, 2, 3, 4], target: 121)
Output:
(1.0 - (3.0 * 4.0)) ^ 2.0 = 121.0
((3.0 * 4.0) - 1.0) ^ 2.0 = 121.0
(1.0 - (4.0 * 3.0)) ^ 2.0 = 121.0
((4.0 * 3.0) - 1.0) ^ 2.0 = 121.0
Example 2:
search(values: [1, 2, 3], target: 1)
Output:
3.0 / (1.0 + 2.0) = 1.0
(1.0 + 2.0) / 3.0 = 1.0
3.0 - (1.0 * 2.0) = 1.0
(1.0 ^ 2.0) ^ 3.0 = 1.0
(1.0 * 3.0) - 2.0 = 1.0
2.0 - (1.0 ^ 3.0) = 1.0
(1.0 ^ 3.0) ^ 2.0 = 1.0
3.0 / (2.0 + 1.0) = 1.0
(2.0 + 1.0) / 3.0 = 1.0
(2.0 - 1.0) ^ 3.0 = 1.0
3.0 - (2.0 * 1.0) = 1.0
3.0 - (2.0 / 1.0) = 1.0
3.0 - (2.0 ^ 1.0) = 1.0
1.0 ^ (2.0 + 3.0) = 1.0
1.0 ^ (2.0 - 3.0) = 1.0
1.0 ^ (2.0 * 3.0) = 1.0
1.0 ^ (2.0 / 3.0) = 1.0
1.0 ^ (2.0 ^ 3.0) = 1.0
2.0 / (3.0 - 1.0) = 1.0
(3.0 - 1.0) / 2.0 = 1.0
(3.0 * 1.0) - 2.0 = 1.0
(3.0 / 1.0) - 2.0 = 1.0
(3.0 ^ 1.0) - 2.0 = 1.0
1.0 ^ (3.0 + 2.0) = 1.0
1.0 * (3.0 - 2.0) = 1.0
1.0 / (3.0 - 2.0) = 1.0
1.0 ^ (3.0 - 2.0) = 1.0
(3.0 - 2.0) * 1.0 = 1.0
(3.0 - 2.0) / 1.0 = 1.0
(3.0 - 2.0) ^ 1.0 = 1.0
1.0 ^ (3.0 * 2.0) = 1.0
1.0 ^ (3.0 / 2.0) = 1.0
1.0 ^ (3.0 ^ 2.0) = 1.0
Eliminating Duplicate Solutions
With 4 or more values, or even with fewer values that aren't unique, you can end up with duplicate expressions. The way to eliminate the duplicates is to use a Set<String> to keep track of the expressions you've already found and check if that set contains your new expression before printing it as a new solution.
import Foundation
// An array of tuples containing an operator name and a closure
// that performs the operation
let ops: [(name: String, function: (Double, Double) -> Double)] = [
("+", { $0 + $1 }),
("-", { $0 - $1 }),
("*", { $0 * $1 }),
("/", { $0 / $1 }),
("^", { pow($0, $1) })
]
func compute(expressions: [String], values: [Double], target: Double, solutions: inout Set<String>) {
// base case of the recursion: if there is only one
// expression and one value, check if the value is the
// target value we're looking for and print the expression
// and value if the target is matched and we don't already
// have that expression in our set of solutions
if expressions.count == 1 {
if values[0] == target && !solutions.contains(expressions[0]) {
print("\(expressions[0]) = \(values[0])")
solutions.insert(expressions[0])
}
} else if expressions.count >= 2 {
// loop through all of the expressions choosing each
// as the first expression
for idx1 in expressions.indices {
// copy the expressions and values arrays so that
// we can remove the expression and value
// without modifying the original arrays
// which will be needed for the next try
var expcopy = expressions
var valcopy = values
let exp1 = expcopy.remove(at: idx1)
let val1 = valcopy.remove(at: idx1)
// loop through the remaining expressions to find
// the second one
for idx2 in expcopy.indices {
// again, copy the arrays to keep from modifying
// the originals while searching
var expcopy2 = expcopy
var valcopy2 = valcopy
let exp2 = expcopy2.remove(at: idx2)
let val2 = valcopy2.remove(at: idx2)
// now try all possible operations to combine
// the two expressions
for op in ops {
// use the op's function to compute the value
let val = op.function(val1, val2)
// combine the expressions into a new string
// expression with the operator in the
// middle and surrounded by () if this is
// not the top level expression
var exp = "\(exp1) \(op.name) \(exp2)"
if !expcopy2.isEmpty {
exp = "(\(exp))"
}
// now that we've reduced the number of
// expressions by 1, recurse by calling
// compute again on the reduced list of
// expressions
let newexp = expcopy2 + [exp]
let newval = valcopy2 + [val]
compute(expressions: newexp, values: newval, target: target, solutions: &solutions)
}
}
}
}
}
// This helper function creates the array of expressions from
// the array of values, creates a Set to hold the solutions, and
// then calls the main function above to do the real work
func search(values: [Double], target: Double) {
// create a set to keep track of solutions found so far
var solutions = Set<String>()
compute(expressions: values.map { String($0) }, values: values, target: target, solutions: &solutions)
print("\n\(solutions.count) unique solutions were found")
}
Example:
search(values: [2, 2, 1], target: 5)
Output:
1.0 + (2.0 + 2.0) = 5.0
(2.0 + 2.0) + 1.0 = 5.0
1.0 + (2.0 * 2.0) = 5.0
(2.0 * 2.0) + 1.0 = 5.0
1.0 + (2.0 ^ 2.0) = 5.0
(2.0 ^ 2.0) + 1.0 = 5.0
2.0 + (2.0 + 1.0) = 5.0
(2.0 + 1.0) + 2.0 = 5.0
2.0 + (1.0 + 2.0) = 5.0
(1.0 + 2.0) + 2.0 = 5.0
10 unique solutions were found
A simple approach not covered in the solutions referenced in the first few comments is to generate your candidate expressions in reverse polish notation (RPN). If you've studied CS, or owned a HP calculator, you might recall this. RPN has the advantage that it contains no parentheses and is evaluated in strict left-to-right order. Follow the link for a full description, here are a couple of examples:
Algebraic: (a+b)*c
RPN: ab+c*
Algebraic: a+(b*c)
RPN: abc*+
In outline to evaluate an RPN expression left-to-right you push any variable you find onto a stack. For any operator you pop 2 values of the stack, combine the with the operation, and push the result back onto the stack.
To generate a single expression for your problem an outline algorithm is:
while there are variables unused or fewer than (number of variables - 1) operators
either:
add any unused variable
or:
if the number of added variables is at least two greater than the
number of added operators add any operator
That will give you a single expression, to generate all of them think recursion. At each stage you iterate through all the choices as above and for each one recurse passing in the partial expression, unused variables, etc. You can store the partial expression in an array, each element being a variable or an operator (think enum). As Swift passes arrays by value as you recurse each call can continue to add elements to the array without effecting other calls.
In pseudocode:
generate(expression: array, variables: variable collection) -> collection
results <- empty collection
for nextVar in variables
add generate(expression + nextVar, variables - nextVar) to results
if #variables in expression - #operators in expression >= 2
for every possible operator
add generate(expression + operator, variables) to results
return results
When a complete expression is generated your can evaluate it and add it to solutions if the result is 24. As a possible optimisation you can evaluate as you go down the recursion to save recalculation of the partial expressions. RPN evaluation can use a stack, which you can build from an array in Swift and pass down in each recursive call. Exploring other optimisation is left to you.
If you get stuck after designing your algorithm and writing some code you can ask a new question - include a link to this one, your algorithm, your code, and your problem; someone will undoubtedly help you along.
HTH

Receiving NaN as an output when using the pow() function to generate a Decimal

I've been at this for hours so forgive me if I'm missing something obvious.
I'm using the pow(_ x: Decimal, _ y: Int) -> Decimal function to help generate a monthly payment amount using a basic formula. I have this function linked to the infix operator *** but I've tried using it just by typing out the function and have the same problem.
Xcode was yelling at me yesterday for having too long of a formula, so I broke it up into a couple constants and incorporated that into the overall formula I need.
Code:
precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
infix operator *** : PowerPrecedence
func *** (radix: Decimal, power: Int) -> Decimal {
return (pow((radix), (power)))
}
func calculateMonthlyPayment() {
let rateAndMonths: Decimal = ((0.0199 / 12.0) + (0.0199 / 12.0))
let rateTwo: Decimal = ((1.0+(0.0199 / 12.0)))
loan12YearsPayment[0] = ((rateAndMonths / rateTwo) *** 144 - 1.0) * ((values.installedSystemCost + loanFees12YearsCombined[0]) * 0.7)
When I print to console or run this in the simulator, the output is NaN. I know the pow function itself is working properly because I've tried it with random integers.
Kindly find my point of view for this Apple function implementation, Note the following examples:
pow(1 as Decimal, -2) // 1; (1 ^ Any number) = 1
pow(10 as Decimal, -2) // NAN
pow(0.1 as Decimal, -2) // 100
pow(0.01 as Decimal, -2) // 10000
pow(1.5 as Decimal, -2) // NAN
pow(0.5 as Decimal, -2) // NAN
It seems like, pow with decimal don't consider any floating numbers except for 10 basis. So It deals with:
0.1 ^ -2 == (1/10) ^ -2 == 10 ^ 2 // It calculates it appropriately, It's 10 basis 10, 100, 1000, ...
1.5 ^ -2 == (3/2) ^ -2 // (3/2) is a floating number ,so deal with it as Double not decimal, It returns NAN.
0.5 ^ -2 == (1/2) ^ -2 // (2) isn't 10 basis, So It will be dealt as (1/2) as It is, It's a floating number also. It returns NAN.

Odd division result in swift [duplicate]

I'm trying to make a math app with different equations and formulas but I'm trying to circle sector but i just wanted to try to divide the input value by 360 but when I do that it only says 0 unless the value is over 360. I have tried using String, Double and Float with no luck I don't know what I'm doing is wrong but down here is the code. I'm thankful for help but I have been sitting a while and searched online for an answer with no result I might have been searching with the wrong search.
if graderna.text == ""{
}
else{
var myInt: Int? = Int(graderna.text!) // conversion of string to Int
var myInt2: Int? = Int(radien.text!)
let pi = 3.1415926
let lutning = 360
let result = (Double(myInt! / lutning) * Double(pi))
svar2.text = "\(result)"
}
Your code is performing integer division, taking the integer result and converting it to a double. Instead, you want to convert these individual integers to doubles and then do the division. So, instead of
let result = (Double(myInt! / lutning) * Double(pi))
You should
let result = Double(myInt!) / Double(lutning) * Double(pi)
Note, Double already has a .pi constant, so you can remove your pi constant, and simplify the above to:
let result = Double(myInt!) / Double(lutning) * .pi
Personally, I’d define myInt and lutning to be Double from the get go (and, while we’re at it, remove all of the forced unwrapping (with the !) of the optionals):
guard
let text = graderna.text,
let text2 = radien.text,
let value = Double(text),
let value2 = Double(text2)
else {
return
}
let lutning: Double = 360
let result = value / lutning * .pi
Or, you can use flatMap to safely unwrap those optional strings:
guard
let value = graderna.text.flatMap({ Double($0) }),
let value2 = radien.text.flatMap({ Double($0) })
else {
return
}
let lutning: Double = 360
let result = value / lutning * .pi
(By the way, if you’re converting between radians and degrees, it should be 2π/360, not π/360.)
You are dividing an Int by an Int.
Integer division rounds to the nearest integer towards zero. Therefore for example 359 / 360 is not a number close to 1, it is 0. 360 / 360 up to 719 / 360 equals 1. 720 / 360 to 1079 / 360 equals 2, and so on.
But your use of optionals is atrocious. I'd write
let myInt = Int(graderna.text!)
let myInt2 = Int(radien.text!)
if let realInt = myInt, realInt2 = myInt2 {
let pi = 3.1415926
let lutning = 360.0
let result = Double (realInt) * (pi / lutning)
svar2.text = "\(result)"
}
In the line let result = (Double(myInt! / lutning) * Double(pi)) you cast your type to double after dividing two integers so your result will always be zero. You have to make them doubles before division.
let result = (Double(myInt!) / Double(lutning)) * Double(pi))
If you want the value should be correct, then try as
let division = ((Float(V1) / Float(V2)) * Float(pi))

Why can't I divide integers correctly within reduce in Swift?

I'm trying to get the average of an array of Ints using the following code:
let numbers = [1,2,3,4,5]
let avg = numbers.reduce(0) { return $0 + $1 / numbers.count }
print(avg) // 1
Which is obviously incorrect. However, if I remove the division to the outside of the closure:
let numbers = [1,2,3,4,5]
let avg = numbers.reduce(0) { return $0 + $1 } / numbers.count
print(avg) // 3
Bingo! I think I remember reading somewhere (can't recall if it was in relation to Swift, JavaScript or programming math in general) that this has something to do with the fact that dividing the sum by the length yields a float / double e.g. (1 + 2) / 5 = 0.6 which will be rounded down within the sum to 0. However I would expect ((1 + 2) + 3) / 5 = 1.2 to return 1, however it too seems to return 0.
With doubles, the calculation works as expected whichever way it's calculated, as long as I box the count integer to a double:
let numbers = [1.0,2.0,3.0,4.0,5.0]
let avg = numbers.reduce(0) { return $0 + $1 / Double(numbers.count) }
print(avg) // 3
I think I understand the why (maybe not?). But I can't come up with a solid example to prove it.
Any help and / or explanation is very much appreciated. Thanks.
The division does not yield a double; you're doing integer division.
You're not getting ((1 + 2) + 3 etc.) / 5.
In the first case, you're getting (((((0 + (1/5 = 0)) + (2/5 = 0)) + (3/5 = 0)) + (4/5 = 0)) + (5/5 = 1)) = 0 + 0 + 0 + 0 + 0 + 1 = 1.
In the second case, you're getting ((((((0 + 1) + 2) + 3) + 4) + 5) / 5) = 15 / 5 = 3.
In the third case, double precision loss is much smaller than the integer, and you get something like (((((0 + (1/5.0 = 0.2)) + (2/5.0 = 0.4)) + (3/5.0 = 0.6)) + (4/5.0 = 0.8)) + (5/5.0 = 1.0)).
The problem is that what you are attempting with the first piece of code does not make sense mathematically.
The average of a sequence is the sum of the entire sequence divided by the number of elements.
reduce calls the lambda function for every member of the collection it is being called on. Thus you are summing and dividing all the way through.
For people finding it hard to understand the original answer.
Consider.
let x = 4
let y = 3
let answer = x/y
You expect the answer to be a Double, but no, it is an Int. For you to get an answer which is not a rounded down Int. You must explicitly state the values to be Double. See below
let doubleAnswer = Double(x)/Double(y)
Hope this helped.