Swift compound arithmetic operation ERROR
The full error message can be found in the Build log in the Report Navigator:
main.swift:15:66: error: cannot invoke '+' with an argument list of type '($T24, $T31)'
var ret = -100.0 + (2.0 * 1.3) + (3.0 * 4.0) + (0.2 * 2.0 * 2.0) + 0.1 * 2.0 * 3.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
main.swift:15:66: note: expression was too complex to be solved in reasonable time;
consider breaking up the expression into distinct sub-expressions
var ret = -100.0 + (2.0 * 1.3) + (3.0 * 4.0) + (0.2 * 2.0 * 2.0) + 0.1 * 2.0 * 3.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
So yes, this expression is too complex for the current (beta 6) Swift compiler.
I would suggest to file a bug report.
At present, the only workaround seems to be to split the expression in two parts,
e.g.
var ret = -100.0 + (2.0 * 1.3) + (3.0 * 4.0)
ret += (0.2 * 2.0 * 2.0) + 0.1 * 2.0 * 3.0
Of course the parentheses are not necessary here, but removing them does not solve
the problem with the original expression.
Strange Swift numbers type casting
Yes, I also found this quite surprising. Double
conforms to both FloatLiteralConvertible
and IntegerLiteralConvertible
(ExpressibleByFloatLiteral
and ExpressibleByIntegerLiteral
in Swift 3). Therefore aDouble
can be initialized with floating point literal
let a = 3.0
or with an integer literal:
let b : Double = 10
(The same is true for other floating point types like Float
andCGFloat
.)
Now it might be unexpected for all of us with an (Objective-)C background
that both statements
let x : Double = 10/4 // x = 2.5 . Really? Yes!
let y = 10/4 as Double // Same here ...
assign the value 0.25
to the variable. From the context, the result of the
division must be a Double
and Swift does not implicitly convert types.
Therefore /
must be the floating point division operator
func /(lhs: Double, rhs: Double) -> Double
so the compiler creates both arguments as Double
s from the literals
"10" and "4". (If 10/4
were treated as the division of two integers
then the result would also be an integer, and that cannot be assigned
to a Double
.)
Note that this is different from
let z = Double(10/4) // z = 2.0 . (I just thought that I understood it &%$!?)
which does an integer division and converts the result to Double
.Double
has an init(_ v: Int)
constructor, and therefore 10/4
can be treated as the division of two integers here.
It really looks a bit strange if we summarize these results:
let x : Double = 10/4 // x = 2.5
let y = 10/4 as Double // y = 2.5
let z = Double(10/4) // z = 2.0
Now we can apply these results to your expression
(10 / 3.0) - (10 / 3)
The first part (10 / 3.0)
can only be a Double
, therefore -
must be the floating point subtraction operator
func -(lhs: Double, rhs: Double) -> Double
and thus (10 / 3)
must also be a Double
. Again, /
must be the floating point division operator, so 10
and 3
are treated as Double
constants.
Therefore the expression is equivalent to
(Double(10) / 3.0) - (Double(10) / Double(3))
and evaluates to 0.0
. If you change the expression to
(10 / 3.0) - Double(10 / 3)
then the result is 0.333...
because in this context, 10 / 3
is the division of two integer constants, as explained above.
Swift Math Operations on small Float Values
The Swift Floating-Point Number documentation states:
Note
Double has a precision of at least 15 decimal digits, whereas the precision of Float can be as little as 6 decimal digits. The appropriate floating-point type to use depends on the nature and range of values you need to work with in your code. In situations where either type would be appropriate, Double is preferred.
In this case, it looks like the error is on the order of 4.060564999999999e-09
in each subtraction, based on the amount left over after 200 subtractions. Indeed changing Float to Double reduces the precision such that the loop runs until i = 0.00499999999999918
when it should be 0.005
.
That is all well and good, however we still have the problem of construction a loop that will run until i
becomes zero. If the amount that you reduce i
by remains constant throughout the loop, one only slightly unfortunate work around is:
var x: Double = 1
let reduction = 0.005
for var i = Int(x/reduction); i >= 0; i -= 1, x = Double(i) * reduction {
println(x)
}
In this case your error won't compound since we are using an integer to index how many reductions we need to reach the current x
, and thus is independent of the length of the loop.
Swift: initializer 'init(_:)' requires that 'Decimal' conform to 'BinaryInteger'
It would be easier to use the Double func pow(_: Double, _: Double) -> Double
instead of using Decimal func pow(_ x: Decimal, _ y: Int) -> Decimal
considering that you want to return a Double:
@discardableResult
func calculateAmount() -> Double {
amount = p * pow(1 + (r / Double(n)), Double(n) * Double(t))
return amount
}
Why is there no need to explicitly cast in case of integers?
If you look at the JLS 4.2.2 Integer Operations, it states that the result of a numerical operation between two integral operands is an int
or a long
. Since there's no implicit cast from an int
to byte
or a short
, you need an explicit cast.
Casting to a type held in a variable
Swift (currently) requires the Type assignment at compile time. You can do some things like this, but you will need to write a converter for each type combination you want to use, e.g:
func convertType(from item: Int) -> Float {
return Float(item)
}
var item: Float = convertType(from: 1)
I would caution going down this road and try and get used to Swift's way of doing things. If you absolutely need it you should be able to use some generic functions with a protocol like FloatConvertable
to handle this more simply.
Related Topics
How to Remove Items from an Array When Deselecting a Row in a UItableview
Add Assets to an Icloud Shared Photo Album Programmatically
Getting an Ip Address and Port Number from a Sockaddr_In Struct in Swift
Sandbox Entitlement to Script Itunes via Nsapplescript
Swiching Between 2 Diferent Nsviewcontrollers with Data
Will a a Weak Wrapper Class Throw Off a Hashable Based Collection When The Wrapped Value Is Set Nil
Syntax to Create Dictionary in Swift
Implementing a Custom Viewmodifier Where Output Is Conditional on Concrete View Type (Swiftui)
Swift 3 Cocoa: Use Quicklook to Preview File in Os X
A Warning "'Init()' Is Deprecated". [Swift, iOS App, Learning Model]
Add Custom .Colornames to UIcolor Somehow
Skphysicscontact Not Detecting Categorybitmask Collision
What's a Placeholder? Why Do We Need to Define Placeholder Data Type for Generics
How to Name File Stored to Files App via Uactivityviewcontroller
When Creating Thread Safe Reads in Swift, Why Is a Variable Create Outside The Concurrent Queue