Reputation: 23
I am new to Swift and can't figure out why I am getting the following error:
exit status 1
main.swift:17:13: error: cannot convert value of type 'Int' to expected argument type 'Bool'
else if remainder2 && remainder == 0{
^~~~~~~~~~
main.swift:21:12: error: cannot convert value of type 'Int' to expected argument type 'Bool'
else if remainder && remainder3 == 0 {
^~~~~~~~~
For the following code:
var aYear = Int(readLine()!)!
func isLeap(year: Int) {
let remainder = year % 4
let remainder2 = year % 400
let remainder3 = year % 100
var whatLeap = false
if remainder == 0 {
whatLeap = true
} else if remainder2 && remainder == 0 {
whatLeap = true
} else if remainder && remainder3 == 0 {
whatLeap = false
} else {
whatLeap = false
}
if whatLeap == true {
print("YES")
} else {
print("NO")
}
}
isLeap(year: aYear)
I have tried changing the variable "whatLeap" to a String, but I get a similar error.
Any help will be greatly appreciated!
Upvotes: 2
Views: 1750
Reputation: 21
I have reached a new and shorter solution that actually works.
func isLeap(year: Int) {
var leap = "NO"
//IF divisible by 4 with no remainders.
if year % 4 == 0 {
leap = "YES"
//Is leap year, unless:
}
if year % 100 == 0 {
leap = "NO"
//Is not leap year, unless:
}
if year % 400 == 0 {
leap = "YES"
//Is leap year.
}
print(leap)
}
Upvotes: -1
Reputation: 63167
I have some improvements to suggest:
Numbered variables are almost always a bad idea. Why should people have to constantly glance up and down between the usages/definitions, to see which one is which one is which, when you can just label them directly? It's particularly aggregious here, when the number variables represent 4
, 400
, 100
, unlike what I presume most people would expect, 4
, 100
, 400
. I would recommend you use descriptive names:
func isLeap(year: Int) {
let remainderMod4 = year % 4
let remainderMod100 = year % 100
let remainderMod400 = year % 400
var isLeapYear = false
if remainderMod4 == 0 {
isLeapYear = true
} else if remainderMod400 == 0 && remainderMod4 == 0 {
isLeapYear = true
} else if remainderMod400 == 0 && remainderMod100 == 0 {
isLeapYear = false
} else {
isLeapYear = false
}
if isLeapYear == true {
print("YES")
} else {
print("NO")
}
}
Don't set temporary values that will be immediately overwritten. Instead, declare the value without initializing it. There is a neat feature of the Swift compiler called "definite initialization", which guarentees that all variables are set at least once before use. Using it earlier than that would cause an error to alert you of the mistake. Because you're never mutating the value, isLeapYear
can be promoted to a let
constant.
let isLeapYear: Bool
Don't compare a boolean to true. Checking for true
is already what if
does. That just yields the same boolean. There are some exceptions (e.g. checking if a Bool?
is true
, not false
or nil
), but anyway:
if isLeapYear { // ...
Don't use x & y == 0
. Use x.isMultiple(of: y)
instead, it's much more clear.
let remainderMod4 = year.isMultiple(of: 4)
let remainderMod100 = year.isMultiple(of: 400)
let remainderMod400 = year.isMultiple(of: 400)
At that point, remainderMod4
reads pretty much the same as year.isMultiple(of: 4)
, so just inline it:
if year.isMultiple(of: 4) == 0 {
isLeapYear = true
} else if year.isMultiple(of: 400) == 0 && year.isMultiple(of: 4) == 0 {
isLeapYear = true
} else if year.isMultiple(of: 400) == 0 && year.isMultiple(of: 100) == 0 {
isLeapYear = false
} else {
isLeapYear = false
}
You can remove your complex if/else branch by using a simpler boolean expression:
let isLeapYear = (year.isMultiple(of: 4) && !year.isMultiple(of: 100))
|| year.isMultiple(of: 400)
You leap-year calculation should only do one thing: figure out if a given year is a leap year. It would be inappropriate for its job to also print out the result to a user. Do that in a separate function, or for a one-off like this, in the global "script area":
func isLeap(year: Int) -> Bool {
return (year.isMultiple(of: 4) && !year.isMultiple(of: 100))
|| year.isMultiple(of: 400)
}
let aYear = Int(readLine()!)!
if isLeap(year: aYear) {
print("YES")
} else {
print("NO")
}
Upvotes: 0
Reputation: 268
You need to compare both variables to 0 otherwise you are saying if remainder2 exists and remainder == 0.
if remainder == 0 {
whatLeap = true
} else if remainder2 == 0 && remainder == 0 {
whatLeap = true
} else if remainder == 0 && remainder3 == 0 {
whatLeap = false
}
Upvotes: 1
Reputation: 1091
You need to state the two statements fully:
remainder2 == 0 && remainder == 0
What you are saying if you leave the statement as is is remainder2 == true && remainder == 0
, which would explain why you get the error message Int to Bool.
To give another example:
var tOrF = false
if tOrF == true {}
and if tOrF {}
are same statements.
Upvotes: 3