Swift: Double/Float is not getting decimal values - ios

I'm trying to get the decimals in simple division but is always returning zero:
(lldb) po Double(20 / 100)
0.0
(lldb) po Float(20 / 100)
0.0
Any of you knows why is returning zero? or there is a way to get the of 0.20 ?
I'll really appreciate your help

20 / 100 is an integer division, and so is 0 (since 100 > 20). That 0 is passed to Double.init.
You want floating point division:
20.0/100.0
You can also use 20.0/100 since a Double divided by an Int is a Double, or 20/100.0 for the same reason.
None of these will return 0.20 exactly, since that can't be represented by Double. 20.0/100 is 0.20000000000000001. But I assume this is what you're looking for.

Related

How do I round a number in lua to a specific decimal digit?

I need a way to round my decimal in lua.
Sometimes my number looks like this:
When I search for it online, I only find solutions to round it to a whole number, but I don't want to round my variable to 0.00, 1.00, or 2.00, how would I round it to a specific decimal digit?
Code:
health = 1
maxhp = 2
function hp_showcase()
makeLuaText("hpcounter", "HP: "..health.."/"..maxhp.."", 2250, 30, 350)
addLuaText("hpcounter")
end
function opponentNoteHit(id, noteData, noteType, isSustainNote)
hp_showcase();
end
You can define a function that takes in the value to be rounded and the digit position you would like to round to, for this example positions in front of the . are positive and behind are negative so 2 rounds to the nearest 100 and -2 rounds to the nearest 0.01
local value = 0.79200750000001
local function round(number, digit_position)
local precision = math.pow(10, digit_position)
number = number + (precision / 2); -- this causes value #.5 and up to round up
-- and #.4 and lower to round down.
return math.floor(number / precision) * precision
end
print(value)
print(round(value, -2))
print(round(value, -1))
print(round(value, 0))
Results:
0.79200750000001
0.79
0.8
1

What does "% is unavailable: Use truncatingRemainder instead" mean?

I get the following error when using code for an extension, I'm not sure if they're asking to just use a different operator or modify the values in the expression based on an internet search.
Error: % is unavailable: Use truncatingRemainder instead
Extension code:
extension CMTime {
var durationText:String {
let totalSeconds = CMTimeGetSeconds(self)
let hours:Int = Int(totalSeconds / 3600)
let minutes:Int = Int(totalSeconds % 3600 / 60)
let seconds:Int = Int(totalSeconds % 60)
if hours > 0 {
return String(format: "%i:%02i:%02i", hours, minutes, seconds)
} else {
return String(format: "%02i:%02i", minutes, seconds)
}
}
}
The error(s) occur when setting the minutes and seconds variables.
CMTimeGetSeconds() returns a floating point number (Float64 aka
Double). In Swift 2 you could compute the
remainder of a floating point division as
let rem = 2.5 % 1.1
print(rem) // 0.3
In Swift 3 this is done with
let rem = 2.5.truncatingRemainder(dividingBy: 1.1)
print(rem) // 0.3
Applied to your code:
let totalSeconds = CMTimeGetSeconds(self)
let hours = Int(totalSeconds / 3600)
let minutes = Int((totalSeconds.truncatingRemainder(dividingBy: 3600)) / 60)
let seconds = Int(totalSeconds.truncatingRemainder(dividingBy: 60))
However, in this particular case it is easier to convert the duration
to an integer in the first place:
let totalSeconds = Int(CMTimeGetSeconds(self)) // Truncate to integer
// Or:
let totalSeconds = lrint(CMTimeGetSeconds(self)) // Round to nearest integer
Then the next lines simplify to
let hours = totalSeconds / 3600
let minutes = (totalSeconds % 3600) / 60
let seconds = totalSeconds % 60
The % modulus operator is defined only for integer types. For floating-point types, you need to be more specific about the kind of IEEE 754 division/remainder behavior you want, so you have to call a method: either remainder or truncatingRemainder. (If you're doing floating-point math you actually need to care about this, and lots of other stuff, or you can get unexpected / bad results.)
If you actually intend to do integer modulus, you need to convert the return value of CMTimeGetSeconds to an integer before using %. (Note that if you do, you'll lop off the fractional seconds... depending on where you're using CMTime that may be important. Do you want minutes:seconds:frames, for example?)
Depending on how you want to present CMTime values in your UI, it might be better to extract the seconds value and pass it to NSDateFormatter or NSDateComponentsFormatter so you get appropriate locale support.
Bring back the simple modulo syntax in swift 3:
This syntax was actually suggested on Apples official swift mailing list here but for some reason they opted for a less elegant syntax.
infix operator %%/*<--infix operator is required for custom infix char combos*/
/**
* Brings back simple modulo syntax (was removed in swift 3)
* Calculates the remainder of expression1 divided by expression2
* The sign of the modulo result matches the sign of the dividend (the first number). For example, -4 % 3 and -4 % -3 both evaluate to -1
* EXAMPLE:
* print(12 %% 5) // 2
* print(4.3 %% 2.1) // 0.0999999999999996
* print(4 %% 4) // 0
* NOTE: The first print returns 2, rather than 12/5 or 2.4, because the modulo (%) operator returns only the remainder. The second trace returns 0.0999999999999996 instead of the expected 0.1 because of the limitations of floating-point accuracy in binary computing.
* NOTE: Int's can still use single %
* NOTE: there is also .remainder which supports returning negatives as oppose to truncatingRemainder (aka the old %) which returns only positive.
*/
public func %% (left:CGFloat, right:CGFloat) -> CGFloat {
return left.truncatingRemainder(dividingBy: right)
}
This simple swift 3 migration tip is part of a more comprehensive swift 3 migration guide with many insights (35k loc / 8-days of migration) http://eon.codes/blog/2017/01/12/swift-3-migration/
There's no need to create a separate modulo operator for floating point numbers, unless you think it makes the code safer. You can overload the % operator to accept floating point numbers like so:
func %<N: BinaryFloatingPoint>(lhs: N, rhs: N) -> N {
lhs.truncatingRemainder(dividingBy: rhs)
}
Usage
let a: Float80 = 10
let b: Float80 = 3
print(a % b)
You can now use % with any two floating point numbers of the same tye.
I found that the following works in Swift 3:
let minutes = Int(floor(totalSeconds / 60))
let seconds = Int(totalSeconds) % 60
where totalSeconds is a TimeInterval (Double).

Swift roundf not working with float value

let amount:Float = 2.235
print("\(roundf(self.amountTax * 100) / 100)")
it returns 2.23
but it should be 2.24
The result is 2.23 because amount * 100 is 223.5 and the rounding of that is 223 (because 2.235 probably has no exact representation, but is something like 2.234999999999) , and divided by 100 it results in 2.23.
You may want to use the ceilf unction instead:
print("(ceilf(amount * 100) / 100)")
This playground result may give you more understanding:

Why don't these numbers add in Xcode Debugger?

I'm using the Xcode debugger, and these numbers don't seem to add. I was curious as to why :
(lldb) p height
(CGFloat) $R0 = 2.1815627849240522E-314
(lldb) p frame.size
(CGSize) $R1 = (width = 375, height = 1000)
(lldb) p frame.size.height
(CGFloat) $R2 = 1000
(lldb) p height + frame.size.height
(CGFloat) $R3 = 1000
I have 3 questions about this..
What is 2.1815627849240522E-314 ? What kind of number is that?
Is it possible to instantiate temporary variables in debugger like you would in Ruby console, Chrome console etc.? For example, let temp_x = 4 ?
Why does my $R3 return 1000 and not.. something bigger?
2.1815627849240522E-314 is essentially zero. 1000 + 0 = 1000.
Floating point numbers have two parts - mantissa and exponent (position of the decimal point). e-341 means "move the decimal point 341 places to the right"
Adding 1000 to that very very small number creates a number that would be equal
1000.000...(> 300 zeros here)...2181567849240522
Even double mantissa can't represent numbers like this (double can represent up to 17 decimal digits) so it takes only the more important numbers in the beginning.
I encourage you to read through What Every Programmer Should Know About Floating-Point Arithmetic

Get randomFloat Fails

Why does my method return values < 0.4 in some cases?
e.g. 0.225501
#define ARC4RANDOM_MAX 0x100000000
float myVar = [self randomFloat:0.4 to:2];
- (float)randomFloat:(int)from to:(int)to
{
return ((double)arc4random() / ARC4RANDOM_MAX) * (to - from) + from;
}
You are casting your parameters to integers (which in your case changes your range to between 0 and 2), change the parameters to be float.
- (float)randomFloat:(float)from to:(float)to
when dividing and using floats the precision of the decimals is sometimes lost. Maybe you can use a long with N fixed number of digits and place the decimal point before those digits. The other day I was getting strange results when adding (1 + (3/10))= should be 1.3 but I always had something like 1.29995 . Hope it helps

Resources