Swift roundf not working with float value - ios

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:

Related

How to math.floor to a decimal in Lua?

print(math.floor(12.5928))
The code above prints 12. What do you do to make it print 12.5?
print(math.floor(12.5928 * 10) / 10)
To generalize the previous answer, this function rounds a number to any number of decimals:
function round(number, decimals)
local power = 10^decimals
return math.floor(number * power) / power
end
Then, round(12.5928, 1) gives 12.5.
print(string.format("%.2f", 129.65686))
for two digits round of
print(math.floor((12.5928) * 100) / 100)

Smart algorithm to create unique exponential sequence steps between two values

I'm looking for a algorithm that returns 5 steps between 2 given dynamic values, including both starting values, with exponential growth. The returned values should be nicely rounded and unique.
Example:
range 100 - 10000 should return something like this:
100, 500, 2500, 5000, 10000
This is what i came up with so far (credit goes mostly to the SO thread I once found but can't recover):
min = 100
max = 10000
a = Array.new
loops = 5
factor = 2.5
for i in 0..loops-1
x = (max - min) * ( (i.to_f / (loops.to_f - 1.0)) ** factor ) + min
case x
when min
a[i] = x.to_i
when max
a[i] = x.to_i
when (min + 1).to_f..500
a[i] = (x.to_f / 250).round(0) * 250
when 500..2000
a[i] = (x.to_f / 500).round(0) * 500
else
a[i] = (x.to_f / 2500).round(0) * 2500
end
end
The result is adjustable with the factor, I found 2.5 to be working best. This works quite well already in most cases. Before rounding I get these values:
[100.0, 409.37, 1850.08, 4922.67, 10000.0]
But it does not check for duplicates that can occur in the rounding process, which happens mostly if the range is smaller:
100 - 1000
Raw: [100.0, 128.12, 259.09, 538.42, 1000.0]
Rounded: [100, 250, 250, 500, 1000]
5000 - 10000
Raw: [5000.0, 5156.25,5883.88, 7435.69, 10000.0]
Rounded: [5000, 5000, 5000, 7500, 10000]
Now I'm a little torn between discarding the whole code and trying to come up with a smarter calculation method that already includes rounding or just checking for duplicates on a second run - but I didn't get a satisfying result from any of those two options.
Does someone have a clue on how to integrate a duplicate check in the rounding or make the rounding more dynamic?

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).

How can I evaluate percentage with Rails / Ruby?

in application.helper I was trying to do this.
However it always get 0. Why?
I want something like 37% 49% 98%
Always integer. no float
def evaluate(number_of_people)
percentage = ((number_of_people / 10000) * 100 ).truncate
"<div class='percentage'>Percentage is #{percentage}%</div>".html_safe
end
You're dividing by an integer, so the result of 3000 / 10000 will be 0.
Divide by 10000.0 instead to force decimal aritmatic.
So change this:
percentage = ((number_of_people / 10000) * 100 ).truncate
To this:
percentage = ((number_of_people / 10000.0) * 100 ).to_i
If your denominator (the 10000 value in this case) is a variable you can use to_f to cast it as a float before dividing.

Generate random number in a float range

How we can generate randomize number between a range in the Float numbers (in delphi xe3) ?
For example, randomize number between [0.10 to 0.90].
I need give results like:
[ 0.20 , 0.32 , 0.10 , 0.50 ]
Thanks for solutions....
Another option is to use RandomRange (returns: AFrom <= r < ATo) as follow:
RandomRange(10, 90 + 1) / 100
or
RandomRange(10, 90 + 1) * 0.01
will return numbers in the range of 0.10 to 0.90 (including 0.90)
var
float : Double;
float := Random; // Random float in range: 0 <= float < 1
float := 0.1 + float*0.8 // 0.1 <= float < 0.9
To initialize the Random number generator, make a single call to Randomizeor set the RandSeed parameter before calling the Random function for the first time.
Not doing so, generates the same sequence every time you run the program. Note however, that this sequence is not guaranteed when recompiling for another compiler version.
Try this:
function RandomRangeF(min, max: single): single;
begin
result := min + Random * (max - min);
end;
This is a bit cheeky but here goes: Depends how many numbers you want after the floating point. For example, if you want 1 number, you could generate in the 100 - 999 range and then divide by 10. Or 1000 - 9999 and divide by 100.

Resources