MT4/MQL4 EA Modification erro - mql4

I have an MT4 EA, trying to modify it, I'll share the part I need to modify it below:
void exit()
{
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
{
if(OrderProfit()<0) //LOSS
{
amountloss=amountloss+OrderProfit();
TotalLotLoss=TotalLotLoss+OrderLots();
lot=lots;
wincount=0;
}
else //profit
{
if(wincount==0)
{
TotalLotLoss=TotalLotLoss+OrderLots();
amountloss=amountloss+OrderProfit();
lot=TotalLotLoss*multi;
wincount=1;
}
else
{
TotalLotLoss=TotalLotLoss+OrderLots();
amountloss=amountloss+OrderProfit();
if(amountloss>0)
{
TotalLotLoss=0;
amountloss=0;
lot=lots;
}
else
{
lot=OrderLots();
}
After 1 win it duplicate all losses by 2 and keep doing this until all losses are recovered, what I want is after 1 recovering win, reset to 0.01
I will give you example:
0.01 loss
0.01 loss
0.01 loss
0.01 loss
0.01 win
0.04 win
then reset to 0.01
that's all
I couldn't figure how to do it! any help?

Related

Hackerrank New Year Chaos Swift

I am trying to solve Hackerrank's New Year Chaos problem in Swift. https://www.hackerrank.com/challenges/new-year-chaos/problem
It is about finding the number of bribes people made on a line waiting for a roller coaster ride. For example, there is a total of 3 bribes in this list [2, 1, 5, 3, 4].
Person 2 bribed person 1.
Person 5 bribed person 3 and 4.
If there are more than 2 bribes by a person, the line becomes "Too chaotic".
I was able to get an exponential solution. However, I want to make it linear.
func minimumBribes(q: [Int]) -> Void {
var bribeCount = 0
var chaotic = false
// for i in 0..<q.count {
// if q[i] - (i + 1) > 2 {
// chaotic = true
// break
// }
//
// for j in i + 1..<q.count {
// if q[i] > q[j] {
// bribeCount += 1
// }
// }
// }
var i = 0
while i < q.count - 1 {
if q[i] - (i + 1) > 2 {
chaotic = true
break
} else if q[i] > i + 1 {
bribeCount += (q[i] - (i + 1))
i += 1
} else if q[i] <= i + 1 && q[i] > q[i + 1] && q.indices.contains(i + 1) {
bribeCount += 1
i += 1
} else { // q[i] < q[i + 1]
i += 1
}
}
if chaotic {
print("Too chaotic")
} else {
print(bribeCount)
}
}
I commented out the exponential solution, which works. But the linear solution does not work and I cannot find out why. It works with the following arrays, [3,2,1,6,5,4], [2,5,1,3,4], [1,2,5,3,7,8,6,4], [1,3,4,2,7,6,5,9,8,11,10,14,13,12].
But there is a really long array in one of the test cases of the problem, which I do not get the correct answer with my linear solution.
For this long array, I get 966 with my exponential solution but the linear solution prints 905.
[2,1,5,6,3,4,9,8,11,7,10,14,13,12,17,16,15,19,18,22,20,24,23,21,27,28,25,26,30,29,33,32,31,35,36,34,39,38,37,42,40,44,41,43,47,46,48,45,50,52,49,51,54,56,55,53,59,58,57,61,63,60,65,64,67,68,62,69,66,72,70,74,73,71,77,75,79,78,81,82,80,76,85,84,83,86,89,90,88,87,92,91,95,94,93,98,97,100,96,102,99,104,101,105,103,108,106,109,107,112,111,110,113,116,114,118,119,117,115,122,121,120,124,123,127,125,126,130,129,128,131,133,135,136,132,134,139,140,138,137,143,141,144,146,145,142,148,150,147,149,153,152,155,151,157,154,158,159,156,161,160,164,165,163,167,166,162,170,171,172,168,169,175,173,174,177,176,180,181,178,179,183,182,184,187,188,185,190,189,186,191,194,192,196,197,195,199,193,198,202,200,204,205,203,207,206,201,210,209,211,208,214,215,216,212,218,217,220,213,222,219,224,221,223,227,226,225,230,231,229,228,234,235,233,237,232,239,236,241,238,240,243,242,246,245,248,249,250,247,244,253,252,251,256,255,258,254,257,259,261,262,263,265,264,260,268,266,267,271,270,273,269,274,272,275,278,276,279,277,282,283,280,281,286,284,288,287,290,289,285,293,291,292,296,294,298,297,299,295,302,301,304,303,306,300,305,309,308,307,312,311,314,315,313,310,316,319,318,321,320,317,324,325,322,323,328,327,330,326,332,331,329,335,334,333,336,338,337,341,340,339,344,343,342,347,345,349,346,351,350,348,353,355,352,357,358,354,356,359,361,360,364,362,366,365,363,368,370,367,371,372,369,374,373,376,375,378,379,377,382,381,383,380,386,387,384,385,390,388,392,391,389,393,396,397,394,398,395,401,400,403,402,399,405,407,406,409,408,411,410,404,413,412,415,417,416,414,420,419,422,421,418,424,426,423,425,428,427,431,430,429,434,435,436,437,432,433,440,438,439,443,441,445,442,447,444,448,446,449,452,451,450,455,453,454,457,456,460,459,458,463,462,464,461,467,465,466,470,469,472,468,474,471,475,473,477,476,480,479,478,483,482,485,481,487,484,489,490,491,488,492,486,494,495,496,498,493,500,499,497,502,504,501,503,507,506,505,509,511,508,513,510,512,514,516,518,519,515,521,522,520,524,517,523,525,526,529,527,531,528,533,532,534,530,537,536,539,535,541,538,540,543,544,542,547,548,545,549,546,552,550,551,554,553,557,555,556,560,559,558,563,562,564,561,567,568,566,565,569,572,571,570,575,574,577,576,579,573,580,578,583,581,584,582,587,586,585,590,589,588,593,594,592,595,591,598,599,596,597,602,603,604,605,600,601,608,609,607,611,612,606,610,615,616,614,613,619,618,617,622,620,624,621,626,625,623,628,627,631,630,633,629,635,632,637,636,634,638,640,642,639,641,645,644,647,643,646,650,648,652,653,654,649,651,656,658,657,655,661,659,660,663,664,666,662,668,667,670,665,671,673,669,672,676,677,674,679,675,680,678,681,684,682,686,685,683,689,690,688,687,693,692,691,696,695,698,694,700,701,702,697,704,699,706,703,705,709,707,711,712,710,708,713,716,715,714,718,720,721,719,723,717,722,726,725,724,729,728,727,730,733,732,735,734,736,731,738,737,741,739,740,744,743,742,747,746,745,750,748,752,749,753,751,756,754,758,755,757,761,760,759,764,763,762,767,765,768,766,771,770,769,774,773,776,772,778,777,779,775,781,780,783,784,782,786,788,789,787,790,785,793,791,792,796,795,794,798,797,801,799,803,800,805,802,804,808,806,807,811,809,810,814,812,813,817,816,819,818,815,820,821,823,822,824,826,827,825,828,831,829,830,834,833,836,832,837,839,838,841,835,840,844,842,846,845,843,849,847,851,850,852,848,855,854,853,857,856,858,861,862,860,859,863,866,865,864,867,870,869,868,872,874,875,871,873,877,878,876,880,881,879,884,883,885,882,888,886,890,891,889,893,887,895,892,896,898,894,899,897,902,901,903,905,900,904,908,907,910,909,906,912,911,915,913,916,918,914,919,921,917,923,920,924,922,927,925,929,928,926,932,931,934,930,933,935,937,939,940,938,936,943,944,942,941,947,946,948,945,951,950,949,953,952,956,954,958,957,955,961,962,963,959,964,966,960,965,969,968,971,967,970,974,972,976,973,975,979,977,981,982,978,980,983,986,984,985,989,988,987,990,993,991,995,994,997,992,999,1000,996,998]
Please help me figure out what is wrong with my solution. Thanks in advance!!
Here is my solution which passes all the test cases :)
func minimumBribes(q: [Int]) -> Void {
var bCount = 0
var isChaotic = false
for (key,value) in q.enumerated() {
if (value - 1) - key > 2 {
isChaotic = true
break
}
for index in stride(from: max(0, value - 2), to: key, by: 1){
if q[index] > value {
bCount += 1
}
}
}
isChaotic ? print("Too chaotic") : print("\(bCount)")
}
What you basically need to do is to first check if the element in each loop is on it's correct position. And if not you find out how much further is it from the right position if its greater than 2 you print "Too chaotic". Your solution is correct uptil this point. But if the difference is less than or equal to 2 then you need to increment the bribes and swap the indices to represent updated array. Furthermore if there are two swaps then you need to represent how the array would be effected by these 2 swaps and hence swap these values before the next iteration to ensure the array is in the condition it would be after these swaps.
Please refer to my solution below. It passes for all test cases:
func swapValues( arr:inout [Int],index:Int, times: Int, bribes:inout Int) -> Bool {
if times == 0 {
return false
}
if arr[index] > arr[index+1] {
let temp = arr[index+1]
arr[index+1] = arr[index]
arr[index] = temp
bribes = bribes + 1
return swapValues(arr: &arr, index: index+1, times: times-1,bribes: &bribes)
}else{
var diff = abs(arr[index+1] - (index+2))
if diff > 2 {
print("Too chaotic")
return true
}
var tooChaotic = swapValues(arr: &arr, index: index+1, times: diff,bribes:&bribes)
if tooChaotic {
return true
}
return swapValues(arr: &arr, index: index, times: times, bribes: &bribes)
}
}
func minimumBribes(q: [Int]) -> Void {
var qC = q
var bribes = 0
var i = 0
while i <= qC.count-1{
if i+1 == qC[i] {
i = i + 1
continue
}
let diff = abs(qC[i] - (i+1))
if diff > 2 {
print("Too chaotic")
return
}
var tooChaotic = swapValues(arr: &qC, index: i, times: diff, bribes: &bribes)
if tooChaotic {
return
}
}
print(bribes)
}
I found this short and easy solution.
func minimumBribes(q: [Int]) -> Void {
var ans = 0
var shouldShow = true
for i in stride(from: (q.count - 1), through: 0, by: -1) {
if (q[i] - (i+1) > 2) {
shouldShow = false
break;
}
for j in stride(from: max(0, q[i] - 2), to: i, by: 1){
if q[j] > q[i] {
ans += 1
}
}
}
if shouldShow {
print(ans)
} else {
print("Too chaotic")
} }
https://github.com/AnanthaKrish/example-ios-apps

why my code is slow when finding Fibonacci sum?

I'm writing answers for project Euler Questions in this repo
but having some performance issues in my solution
Question 2:
Each new term in the Fibonacci sequence is generated by adding the previous two terms.
By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
My Solution is
func solution2()
{
func fibonacci(number: Int) -> (Int)
{
if number <= 1
{
return number
}
else
{
return fibonacci(number - 1) + fibonacci(number - 2)
}
}
var sum = 0
print("calculating...")
for index in 2..<50
{
print (index)
if (fibonacci(index) % 2 == 0)
{
sum += fibonacci(index)
}
}
print(sum)
}
My Question is, why it gets super slow after iteration 42, i want to do it for 4000000 as the question says, any help?
solution 2
func solution2_fast()
{
var phiOne : Double = (1.0 + sqrt(5.0)) / 2.0
var phiTwo : Double = (1.0 - sqrt(5.0)) / 2.0
func findFibonacciNumber (nthNumber : Double) -> Int64
{
let nthNumber : Double = (pow(phiOne, nthNumber) - (pow(phiTwo, nthNumber))) / sqrt(5.0)
return Int64(nthNumber)
}
var sum : Int64 = 0
print("calculating...")
for index in 2..<4000000
{
print (index)
let f = findFibonacciNumber(Double(index))
if (f % 2 == 0)
{
sum += f
}
}
print(sum)
}
The most important thing about PE questions is to think about what it is asking.
This is not asking you to produce all Fibonacci numbers F(n) less than 4000000. It is asking for the sum of all even F(n) less than 4000000.
Think about the sum of all F(n) where F(n) < 10.
1 + 2 + 3 + 5 + 8
I could do this by calculating F(1), then F(2), then F(3), and so on... and then checking they are less than 10 before adding them up.
Or I could store two variables...
F1 = 1
F2 = 2
And a total...
Total = 3
Now I can turn this into a while loop and lose the recursion altogether. In fact, the most complex thing I'm doing is adding two numbers together...
I came up with this...
func sumEvenFibonacci(lessThan limit: Int) -> Int {
// store the first two Fibonacci numbers
var n1 = 1
var n2 = 2
// and a cumulative total
var total = 0
// repeat until you hit the limit
while n2 < limit {
// if the current Fibonacci is even then add to total
if n2 % 2 == 0 {
total += n2
}
// move the stored Fibonacci numbers up by one.
let temp = n2
n2 = n2 + n1
n1 = temp
}
return total
}
It runs in a fraction of a second.
sumEvenFibonacci(lessThan: 4000000)
Finds the correct answer.
In fact this... sumEvenFibonacci(lessThan: 1000000000000000000) runs in about half a second.
The second solution seems to be fast(er) although an Int64 will not be sufficient to store the result. The sum of Fibonacci numbers from 2..91 is 7,527,100,471,027,205,936 but the largest number you can store in an Int64 is 9,223,372,036,854,775,807. For this you need to use some other types like BigInteger
Because you use the recursive, and it cache in the memory.If you iteration 42, it maybe has so many fibonacci function in your memory, and recursive.So it isn't suitable for recursive, and you can store the result in the array, not the reason of the swift.
this is the answer in two different ways
func solution2_recursive()
{
func fibonacci(number: Int) -> (Int)
{
if number <= 1
{
return number
}
else
{
return fibonacci(number - 1) + fibonacci(number - 2)
}
}
var sum = 0
print("calculating...")
for index in 2..<50
{
print (index)
let f = fibonacci(index)
if( f < 4000000)
{
if (f % 2 == 0)
{
sum += f
}
}
else
{
print(sum)
return
}
}
}
solution 2
func solution2()
{
var phiOne : Double = (1.0 + sqrt(5.0)) / 2.0
var phiTwo : Double = (1.0 - sqrt(5.0)) / 2.0
func findFibonacciNumber (nthNumber : Double) -> Int64
{
let nthNumber : Double = (pow(phiOne, nthNumber) - (pow(phiTwo, nthNumber))) / sqrt(5.0)
return Int64(nthNumber)
}
var sum : Int64 = 0
print("calculating...")
for index in 2..<50
{
let f = findFibonacciNumber(Double(index))
if(f < 4000000)
{
if (f % 2 == 0)
{
sum += f
}
}
else
{
print(sum)
return
}
}
}

Generate weighted random number in Swift [duplicate]

Check out this question:
Swift probability of random number being selected?
The top answer suggests to use a switch statement, which does the job. However, if I have a very large number of cases to consider, the code looks very inelegant; I have a giant switch statement with very similar code in each case repeated over and over again.
Is there a nicer, cleaner way to pick a random number with a certain probability when you have a large number of probabilities to consider? (like ~30)
This is a Swift implementation strongly influenced by the various
answers to Generate random numbers with a given (numerical) distribution.
For Swift 4.2/Xcode 10 and later (explanations inline):
func randomNumber(probabilities: [Double]) -> Int {
// Sum of all probabilities (so that we don't have to require that the sum is 1.0):
let sum = probabilities.reduce(0, +)
// Random number in the range 0.0 <= rnd < sum :
let rnd = Double.random(in: 0.0 ..< sum)
// Find the first interval of accumulated probabilities into which `rnd` falls:
var accum = 0.0
for (i, p) in probabilities.enumerated() {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}
Examples:
let x = randomNumber(probabilities: [0.2, 0.3, 0.5])
returns 0 with probability 0.2, 1 with probability 0.3,
and 2 with probability 0.5.
let x = randomNumber(probabilities: [1.0, 2.0])
return 0 with probability 1/3 and 1 with probability 2/3.
For Swift 3/Xcode 8:
func randomNumber(probabilities: [Double]) -> Int {
// Sum of all probabilities (so that we don't have to require that the sum is 1.0):
let sum = probabilities.reduce(0, +)
// Random number in the range 0.0 <= rnd < sum :
let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
// Find the first interval of accumulated probabilities into which `rnd` falls:
var accum = 0.0
for (i, p) in probabilities.enumerated() {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}
For Swift 2/Xcode 7:
func randomNumber(probabilities probabilities: [Double]) -> Int {
// Sum of all probabilities (so that we don't have to require that the sum is 1.0):
let sum = probabilities.reduce(0, combine: +)
// Random number in the range 0.0 <= rnd < sum :
let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
// Find the first interval of accumulated probabilities into which `rnd` falls:
var accum = 0.0
for (i, p) in probabilities.enumerate() {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}
Is there a nicer, cleaner way to pick a random number with a certain probability when you have a large number of probabilities to consider?
Sure. Write a function that generates a number based on a table of probabilities. That's essentially what the switch statement you've pointed to is: a table defined in code. You could do the same thing with data using a table that's defined as a list of probabilities and outcomes:
probability outcome
----------- -------
0.4 1
0.2 2
0.1 3
0.15 4
0.15 5
Now you can pick a number between 0 and 1 at random. Starting from the top of the list, add up probabilities until you've exceeded the number you picked, and use the corresponding outcome. For example, let's say the number you pick is 0.6527637. Start at the top: 0.4 is smaller, so keep going. 0.6 (0.4 + 0.2) is smaller, so keep going. 0.7 (0.6 + 0.1) is larger, so stop. The outcome is 3.
I've kept the table short here for the sake of clarity, but you can make it as long as you like, and you can define it in a data file so that you don't have to recompile when the list changes.
Note that there's nothing particularly specific to Swift about this method -- you could do the same thing in C or Swift or Lisp.
This seems like a good opportunity for a shameless plug to my small library, swiftstats:
https://github.com/r0fls/swiftstats
For example, this would generate 3 random variables from a normal distribution with mean 0 and variance 1:
import SwiftStats
let n = SwiftStats.Distributions.Normal(0, 1.0)
print(n.random())
Supported distributions include: normal, exponential, binomial, etc...
It also supports fitting sample data to a given distribution, using the Maximum Likelihood Estimator for the distribution.
See the project readme for more info.
You could do it with exponential or quadratic functions - have x be your random number, take y as the new random number. Then, you just have to jiggle the equation until it fits your use case. Say I had (x^2)/10 + (x/300). Put your random number in, (as some floating-point form), and then get the floor with Int() when it comes out. So, if my random number generator goes from 0 to 9, I have a 40% chance of getting 0, and a 30% chance of getting 1 - 3, a 20% chance of getting 4 - 6, and a 10% chance of an 8. You're basically trying to fake some kind of normal distribution.
Here's an idea of what it would look like in Swift:
func giveY (x: UInt32) -> Int {
let xD = Double(x)
return Int(xD * xD / 10 + xD / 300)
}
let ans = giveY (arc4random_uniform(10))
EDIT:
I wasn't very clear above - what I meant was you could replace the switch statement with some function that would return a set of numbers with a probability distribution that you could figure out with regression using wolfram or something. So, for the question you linked to, you could do something like this:
import Foundation
func returnLevelChange() -> Double {
return 0.06 * exp(0.4 * Double(arc4random_uniform(10))) - 0.1
}
newItemLevel = oldItemLevel * returnLevelChange()
So that function returns a double somewhere between -0.05 and 2.1. That would be your "x% worse/better than current item level" figure. But, since it's an exponential function, it won't return an even spread of numbers. The arc4random_uniform(10) returns an int from 0 - 9, and each of those would result in a double like this:
0: -0.04
1: -0.01
2: 0.03
3: 0.1
4: 0.2
5: 0.34
6: 0.56
7: 0.89
8: 1.37
9: 2.1
Since each of those ints from the arc4random_uniform has an equal chance of showing up, you get probabilities like this:
40% chance of -0.04 to 0.1 (~ -5% - 10%)
30% chance of 0.2 to 0.56 (~ 20% - 55%)
20% chance of 0.89 to 1.37 (~ 90% - 140%)
10% chance of 2.1 (~ 200%)
Which is something similar to the probabilities that other person had. Now, for your function, it's much more difficult, and the other answers are almost definitely more applicable and elegant. BUT you could still do it.
Arrange each of the letters in order of their probability - from largest to smallest. Then, get their cumulative sums, starting with 0, without the last. (so probabilities of 50%, 30%, 20% becomes 0, 0.5, 0.8). Then you multiply them up until they're integers with reasonable accuracy (0, 5, 8). Then, plot them - your cumulative probabilities are your x's, the things you want to select with a given probability (your letters) are your y's. (you obviously can't plot actual letters on the y axis, so you'd just plot their indices in some array). Then, you'd try find some regression there, and have that be your function. For instance, trying those numbers, I got
e^0.14x - 1
and this:
let letters: [Character] = ["a", "b", "c"]
func randLetter() -> Character {
return letters[Int(exp(0.14 * Double(arc4random_uniform(10))) - 1)]
}
returns "a" 50% of the time, "b" 30% of the time, and "c" 20% of the time. Obviously pretty cumbersome for more letters, and it would take a while to figure out the right regression, and if you wanted to change the weightings you're have to do it manually. BUT if you did find a nice equation that did fit your values, the actual function would only be a couple lines long, and fast.

Generate random numbers with a given distribution

Check out this question:
Swift probability of random number being selected?
The top answer suggests to use a switch statement, which does the job. However, if I have a very large number of cases to consider, the code looks very inelegant; I have a giant switch statement with very similar code in each case repeated over and over again.
Is there a nicer, cleaner way to pick a random number with a certain probability when you have a large number of probabilities to consider? (like ~30)
This is a Swift implementation strongly influenced by the various
answers to Generate random numbers with a given (numerical) distribution.
For Swift 4.2/Xcode 10 and later (explanations inline):
func randomNumber(probabilities: [Double]) -> Int {
// Sum of all probabilities (so that we don't have to require that the sum is 1.0):
let sum = probabilities.reduce(0, +)
// Random number in the range 0.0 <= rnd < sum :
let rnd = Double.random(in: 0.0 ..< sum)
// Find the first interval of accumulated probabilities into which `rnd` falls:
var accum = 0.0
for (i, p) in probabilities.enumerated() {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}
Examples:
let x = randomNumber(probabilities: [0.2, 0.3, 0.5])
returns 0 with probability 0.2, 1 with probability 0.3,
and 2 with probability 0.5.
let x = randomNumber(probabilities: [1.0, 2.0])
return 0 with probability 1/3 and 1 with probability 2/3.
For Swift 3/Xcode 8:
func randomNumber(probabilities: [Double]) -> Int {
// Sum of all probabilities (so that we don't have to require that the sum is 1.0):
let sum = probabilities.reduce(0, +)
// Random number in the range 0.0 <= rnd < sum :
let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
// Find the first interval of accumulated probabilities into which `rnd` falls:
var accum = 0.0
for (i, p) in probabilities.enumerated() {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}
For Swift 2/Xcode 7:
func randomNumber(probabilities probabilities: [Double]) -> Int {
// Sum of all probabilities (so that we don't have to require that the sum is 1.0):
let sum = probabilities.reduce(0, combine: +)
// Random number in the range 0.0 <= rnd < sum :
let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
// Find the first interval of accumulated probabilities into which `rnd` falls:
var accum = 0.0
for (i, p) in probabilities.enumerate() {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}
Is there a nicer, cleaner way to pick a random number with a certain probability when you have a large number of probabilities to consider?
Sure. Write a function that generates a number based on a table of probabilities. That's essentially what the switch statement you've pointed to is: a table defined in code. You could do the same thing with data using a table that's defined as a list of probabilities and outcomes:
probability outcome
----------- -------
0.4 1
0.2 2
0.1 3
0.15 4
0.15 5
Now you can pick a number between 0 and 1 at random. Starting from the top of the list, add up probabilities until you've exceeded the number you picked, and use the corresponding outcome. For example, let's say the number you pick is 0.6527637. Start at the top: 0.4 is smaller, so keep going. 0.6 (0.4 + 0.2) is smaller, so keep going. 0.7 (0.6 + 0.1) is larger, so stop. The outcome is 3.
I've kept the table short here for the sake of clarity, but you can make it as long as you like, and you can define it in a data file so that you don't have to recompile when the list changes.
Note that there's nothing particularly specific to Swift about this method -- you could do the same thing in C or Swift or Lisp.
This seems like a good opportunity for a shameless plug to my small library, swiftstats:
https://github.com/r0fls/swiftstats
For example, this would generate 3 random variables from a normal distribution with mean 0 and variance 1:
import SwiftStats
let n = SwiftStats.Distributions.Normal(0, 1.0)
print(n.random())
Supported distributions include: normal, exponential, binomial, etc...
It also supports fitting sample data to a given distribution, using the Maximum Likelihood Estimator for the distribution.
See the project readme for more info.
You could do it with exponential or quadratic functions - have x be your random number, take y as the new random number. Then, you just have to jiggle the equation until it fits your use case. Say I had (x^2)/10 + (x/300). Put your random number in, (as some floating-point form), and then get the floor with Int() when it comes out. So, if my random number generator goes from 0 to 9, I have a 40% chance of getting 0, and a 30% chance of getting 1 - 3, a 20% chance of getting 4 - 6, and a 10% chance of an 8. You're basically trying to fake some kind of normal distribution.
Here's an idea of what it would look like in Swift:
func giveY (x: UInt32) -> Int {
let xD = Double(x)
return Int(xD * xD / 10 + xD / 300)
}
let ans = giveY (arc4random_uniform(10))
EDIT:
I wasn't very clear above - what I meant was you could replace the switch statement with some function that would return a set of numbers with a probability distribution that you could figure out with regression using wolfram or something. So, for the question you linked to, you could do something like this:
import Foundation
func returnLevelChange() -> Double {
return 0.06 * exp(0.4 * Double(arc4random_uniform(10))) - 0.1
}
newItemLevel = oldItemLevel * returnLevelChange()
So that function returns a double somewhere between -0.05 and 2.1. That would be your "x% worse/better than current item level" figure. But, since it's an exponential function, it won't return an even spread of numbers. The arc4random_uniform(10) returns an int from 0 - 9, and each of those would result in a double like this:
0: -0.04
1: -0.01
2: 0.03
3: 0.1
4: 0.2
5: 0.34
6: 0.56
7: 0.89
8: 1.37
9: 2.1
Since each of those ints from the arc4random_uniform has an equal chance of showing up, you get probabilities like this:
40% chance of -0.04 to 0.1 (~ -5% - 10%)
30% chance of 0.2 to 0.56 (~ 20% - 55%)
20% chance of 0.89 to 1.37 (~ 90% - 140%)
10% chance of 2.1 (~ 200%)
Which is something similar to the probabilities that other person had. Now, for your function, it's much more difficult, and the other answers are almost definitely more applicable and elegant. BUT you could still do it.
Arrange each of the letters in order of their probability - from largest to smallest. Then, get their cumulative sums, starting with 0, without the last. (so probabilities of 50%, 30%, 20% becomes 0, 0.5, 0.8). Then you multiply them up until they're integers with reasonable accuracy (0, 5, 8). Then, plot them - your cumulative probabilities are your x's, the things you want to select with a given probability (your letters) are your y's. (you obviously can't plot actual letters on the y axis, so you'd just plot their indices in some array). Then, you'd try find some regression there, and have that be your function. For instance, trying those numbers, I got
e^0.14x - 1
and this:
let letters: [Character] = ["a", "b", "c"]
func randLetter() -> Character {
return letters[Int(exp(0.14 * Double(arc4random_uniform(10))) - 1)]
}
returns "a" 50% of the time, "b" 30% of the time, and "c" 20% of the time. Obviously pretty cumbersome for more letters, and it would take a while to figure out the right regression, and if you wanted to change the weightings you're have to do it manually. BUT if you did find a nice equation that did fit your values, the actual function would only be a couple lines long, and fast.

How do you round a double in Dart to a given degree of precision AFTER the decimal point?

Given a double, I want to round it to a given number of points of precision after the decimal point, similar to PHP's round() function.
The closest thing I can find in the Dart docs is double.toStringAsPrecision(), but this is not quite what I need because it includes the digits before the decimal point in the total points of precision.
For example, using toStringAsPrecision(3):
0.123456789 rounds to 0.123
9.123456789 rounds to 9.12
98.123456789 rounds to 98.1
987.123456789 rounds to 987
9876.123456789 rounds to 9.88e+3
As the magnitude of the number increases, I correspondingly lose precision after the decimal place.
See the docs for num.toStringAsFixed().
String toStringAsFixed(int fractionDigits)
Returns a decimal-point string-representation of this.
Converts this to a double before computing the string representation.
If the absolute value of this is greater or equal to 10^21 then this methods returns an exponential representation computed by this.toStringAsExponential().
Examples:
1000000000000000000000.toStringAsExponential(3); // 1.000e+21
Otherwise the result is the closest string representation with exactly fractionDigits digits after the decimal point. If fractionDigits equals 0 then the decimal point is omitted.
The parameter fractionDigits must be an integer satisfying: 0 <= fractionDigits <= 20.
Examples:
1.toStringAsFixed(3); // 1.000
(4321.12345678).toStringAsFixed(3); // 4321.123
(4321.12345678).toStringAsFixed(5); // 4321.12346
123456789012345678901.toStringAsFixed(3); // 123456789012345683968.000
1000000000000000000000.toStringAsFixed(3); // 1e+21
5.25.toStringAsFixed(0); // 5
num.toStringAsFixed() rounds. This one turns you num (n) into a string with the number of decimals you want (2), and then parses it back to your num in one sweet line of code:
n = num.parse(n.toStringAsFixed(2));
Direct way:
double d = 2.3456789;
String inString = d.toStringAsFixed(2); // '2.35'
double inDouble = double.parse(inString); // 2.35
Using an extension:
extension Ex on double {
double toPrecision(int n) => double.parse(toStringAsFixed(n));
}
Usage:
void main() {
double d = 2.3456789;
double d1 = d.toPrecision(1); // 2.3
double d2 = d.toPrecision(2); // 2.35
double d3 = d.toPrecision(3); // 2.345
}
Above solutions do not appropriately round numbers. I use:
double dp(double val, int places){
num mod = pow(10.0, places);
return ((val * mod).round().toDouble() / mod);
}
var price = 99.012334554;
price = price.toStringAsFixed(2);
print(price); // 99.01
That is the ref of dart.
ref: https://api.dartlang.org/stable/2.3.0/dart-core/num/toStringAsFixed.html
void main() {
int decimals = 2;
int fac = pow(10, decimals);
double d = 1.234567889;
d = (d * fac).round() / fac;
print("d: $d");
}
Prints:
1.23
I used the toStringAsFixed() method, to round a number to specific numbers after the decimal point
EX:
double num = 22.48132906
and when I rounded it to two numbers like this:
print(num.toStringAsFixed(2)) ;
It printed 22.48
and when I rounded to one number, it printed 22.5
The modified answer of #andyw using Dart Extension methods:
extension Precision on double {
double toPrecision(int fractionDigits) {
double mod = pow(10, fractionDigits.toDouble());
return ((this * mod).round().toDouble() / mod);
}
}
Usage:
var latitude = 1.123456;
var latitudeWithFixedPrecision = latitude.toPrecision(3); // Outputs: 1.123
To round a double in Dart to a given degree of precision AFTER the decimal point, you can use built-in solution in dart toStringAsFixed() method, but you have to convert it back to double
void main() {
double step1 = 1/3;
print(step1); // 0.3333333333333333
String step2 = step1.toStringAsFixed(2);
print(step2); // 0.33
double step3 = double.parse(step2);
print(step3); // 0.33
}
you can simply multiple the value in 100 and then round it and then divide it again into 100.
(number * 100).round() / 100.0;
double value = 2.8032739273;
String formattedValue = value.toStringAsFixed(3);
You can use toStringAsFixed in order to display the limited digits after decimal points. toStringAsFixed returns a decimal-point string-representation. toStringAsFixed accepts an argument called fraction Digits which is how many digits after decimal we want to display. Here is how to use it.
double pi = 3.1415926;
const val = pi.toStringAsFixed(2); // 3.14
Above solutions do not work for all cases. What worked for my problem was this solution that will round your number (0.5 to 1 or 0.49 to 0) and leave it without any decimals:
Input: 12.67
double myDouble = 12.67;
var myRoundedNumber; // Note the 'var' datatype
// Here I used 1 decimal. You can use another value in toStringAsFixed(x)
myRoundedNumber = double.parse((myDouble).toStringAsFixed(1));
myRoundedNumber = myRoundedNumber.round();
print(myRoundedNumber);
Output: 13
This link has other solutions too
You can create a reusable function that accept numberOfDecimal you want to format & utilizing toStringAsFixed() method to format the number and convert it back to double.
FYI, toStringAsFixed method does not round up number that ends with 5 (eg: toStringAsFixed round off 2.275 to 2.27 instead of 2.28). This is the default behaviour of dart toStringAsFixed method (similar to Javascript toFixed)
As a workaround, we can add 1 to the existing number after the last decimal number (eg: Add 0.0001 to 2.275 become 2.2751 & 2.2751 will round off correctly to 2.28)
double roundOffToXDecimal(double number, {int numberOfDecimal = 2}) {
// To prevent number that ends with 5 not round up correctly in Dart (eg: 2.275 round off to 2.27 instead of 2.28)
String numbersAfterDecimal = number.toString().split('.')[1];
if (numbersAfterDecimal != '0') {
int existingNumberOfDecimal = numbersAfterDecimal.length;
number += 1 / (10 * pow(10, existingNumberOfDecimal));
}
return double.parse(number.toStringAsFixed(numberOfDecimal));
}
// Example of usage:
var price = roundOffToXDecimal(2.275, numberOfDecimal: 2)
print(price); // 2.28
I made this extension on double
import 'dart:math';
extension DoubleExtension on double {
/// rounds the double to a specific decimal place
double roundedPrecision(int places) {
double mod = pow(10.0, places) as double;
return ((this * mod).round().toDouble() / mod);
}
/// good for string output because it can remove trailing zeros
/// and sometimes periods. Or optionally display the exact number of trailing
/// zeros
String roundedPrecisionToString(
int places, {
bool trailingZeros = false,
}) {
double mod = pow(10.0, places) as double;
double round = ((this * mod).round().toDouble() / mod);
String doubleToString =
trailingZeros ? round.toStringAsFixed(places) : round.toString();
if (!trailingZeros) {
RegExp trailingZeros = RegExp(r'^[0-9]+.0+$');
if (trailingZeros.hasMatch(doubleToString)) {
doubleToString = doubleToString.split('.')[0];
}
}
return doubleToString;
}
String toStringNoTrailingZeros() {
String doubleToString = toString();
RegExp trailingZeros = RegExp(r'^[0-9]+.0+$');
if (trailingZeros.hasMatch(doubleToString)) {
doubleToString = doubleToString.split('.')[0];
}
return doubleToString;
}
}
Here are the passing tests.
import 'package:flutter_test/flutter_test.dart';
import 'package:project_name/utils/double_extension.dart';
void main() {
group("rounded precision", () {
test("rounding to 0 place results in an int", () {
double num = 5.1234;
double num2 = 5.8234;
expect(num.roundedPrecision(0), 5);
expect(num2.roundedPrecision(0), 6);
});
test("rounding to 1 place rounds correctly to 1 place", () {
double num = 5.12;
double num2 = 5.15;
expect(num.roundedPrecision(1), 5.1);
expect(num2.roundedPrecision(1), 5.2);
});
test(
"rounding a number to a precision that is more accurate than the origional",
() {
double num = 5;
expect(num.roundedPrecision(5), 5);
});
});
group("rounded precision returns the correct string", () {
test("rounding to 0 place results in an int", () {
double num = 5.1234;
double num2 = 5.8234;
expect(num.roundedPrecisionToString(0), "5");
expect(num2.roundedPrecisionToString(0), "6");
});
test("rounding to 1 place rounds correct", () {
double num = 5.12;
double num2 = 5.15;
expect(num.roundedPrecisionToString(1), "5.1");
expect(num2.roundedPrecisionToString(1), "5.2");
});
test("rounding to 2 places rounds correct", () {
double num = 5.123;
double num2 = 5.156;
expect(num.roundedPrecisionToString(2), "5.12");
expect(num2.roundedPrecisionToString(2), "5.16");
});
test("cut off all trailing zeros (and periods)", () {
double num = 5;
double num2 = 5.03000;
expect(num.roundedPrecisionToString(5), "5");
expect(num2.roundedPrecisionToString(5), "5.03");
});
});
}
If you don't want any decimals when the resulting decimals are all zeroes, something like this would work:
String fixedDecimals(double d, int decimals, {bool removeZeroDecimals = true}){
double mod = pow(10.0, decimals);
double result = ((d * mod).round().toDouble() / mod);
if( removeZeroDecimals && result - (result.truncate()) == 0.0 ) decimals = 0;
return result.toStringAsFixed(decimals);
}
This will simply output 9 instead of 9.00 if the input is 9.004 and you want 2 decimals.
Rounding a double, an IEEE-754 binary floating-point number, to a specific number of decimal digits is inherently problematic if you want a double result.
In the same way that fractions such as 1/3 can't be exactly represented with a finite number of decimal digits, many (well, infinitely many) decimal numbers can't be represented with a finite number of binary digits. For example, the decimal number 0.1 cannot be exactly represented in binary. While you could try to round 0.09999 to 0.1, as a double it would actually be "rounded" to 0.1000000000000000055511151231257827021181583404541015625. Most of the other answers that claim to round doubles with decimal precision actually return the nearest representable double. When you display those values to users by converting them to Strings, you might see more digits than you expect.
What you can do is to make the string representation look like a nice, rounded number when you ultimately show it to users, and that's what double.toStringAsFixed() does. That's also why when you print 0.100000000..., you might see 0.1 if the implementation is trying to pretty-print user-friendly values. However, don't be fooled: the double value would never actually be 0.1 exactly, and if you do repeated arithmetic with such inexact values, you can accumulate error (for example: 0.1 + 0.2).
Note that all of the above is fundamental to how binary floating-point numbers work and is not specific to Dart. Also see:
Is floating point math broken?
If you don't understand the above explanations, Tom Scott also made a great video explaining how floating-point works.
Bottom line: If you care about decimal precision, do NOT use binary floating-point types. This is particularly important if you're dealing with money.
You instead should use:
Integers. For example, if you are dealing with currency, instead of using double dollars = 1.23;, use int cents = 123;. Your calculations then always will be exact, and you can convert to the desired units only when displaying them to the user (and likewise can convert in the opposite direction when reading input from the user).
A type designed to represent decimal numbers with arbitrary precision. For example, package:decimal provides a Decimal type. With such a type, some of the other answers (such as multiplying by 100, rounding, and then dividing by 100) then would be appropriate. (But really you should use Decimal.round directly.)
I think the accepted answer is not the perfect solution because it converts to string.
If you don't wanna convert to string and back to a double use
double.toPrecision(decimalNumber) from GetX package.
If you don't wanna use GetX just for this (I highly recommend GetX, it will change your life with flutter) you can copy and paste this.
Remeber to import the file when you wanna use the extention.
import 'dart:math';
extension Precision on double {
double toPrecision(int fractionDigits) {
var mod = pow(10, fractionDigits.toDouble()).toDouble();
return ((this * mod).round().toDouble() / mod);
}
}
if use dynamic type of data. You can use it.
typeDecimal(data) => num.parse(data.toString()).toStringAsFixed(2);
also if you want to round the double value inside the Text.
Text('${carpetprice.toStringAsFixed(3)}',),
Just write this extension on double
extension Round on double {
double roundToPrecision(int n) {
int fac = pow(10, n).toInt();
return (this * fac).round() / fac;
}
}
Never thought this was so complex in Dart but this is my solution:
double truncateDouble(double val, int decimals) {
String valString = val.toString();
int dotIndex = valString.indexOf('.');
// not enough decimals
int totalDecimals = valString.length - dotIndex - 1;
if (totalDecimals < decimals) {
decimals = totalDecimals;
}
valString = valString.substring(0, dotIndex + decimals + 1);
return double.parse(valString);
}
var val = truncateDouble(44.999, 2);
If you want use special rounding. You can try this function (rounding).
void main(List<String> arguments) {
list.map((e) {
log('list1');
rounding(e, 0.05);
rounding(e, 0.1);
rounding(e, 0.2);
rounding(e, 0.25);
rounding(e, 0.5);
rounding(e, 1);
rounding(e, 10);
}).toList();
list2.map((e) {
log('list2');
rounding(e, 0.05);
rounding(e, 0.1);
rounding(e, 0.2);
rounding(e, 0.25);
rounding(e, 0.5);
rounding(e, 1);
rounding(e, 10);
}).toList();
}
const list = [1.11, 1.22, 1.33, 1.44, 1.55, 1.66, 1.77, 1.88, 1.99];
const list2 = [2.19, 3.28, 4.37, 5.46, 6.55, 7.64, 8.73, 9.82, 10.91];
void rounding(double price, double count) {
log('-----------------------');
log('price: $price, count: $count');
double _priceRemainder = price % count;
double _someDiff = count / _priceRemainder;
log('_price: ${_priceRemainder.toStringAsFixed(2)}');
log('_pricePlus: ${_someDiff.toStringAsFixed(2)}');
if (_someDiff.toStringAsFixed(2) == '1.00') {
log('_someDiff = 1');
} else if (_someDiff > 1 && _someDiff <= 2 ||
_someDiff.toStringAsFixed(2) == '2.00') {
log('_someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00');
log('ceilToDouble: $price: ${(price + (count - _priceRemainder)).toStringAsFixed(2)}');
log('floorToDouble: $price: ${(price - _priceRemainder).toStringAsFixed(2)}');
log('roundToDouble: $price: ${(price + (count - _priceRemainder)).toStringAsFixed(2)}');
} else if (_someDiff > 2) {
log('_someDiff > 2');
log('ceilToDouble: $price: ${(price + (count - _priceRemainder)).toStringAsFixed(2)}');
log('floorToDouble: $price: ${(price - _priceRemainder).toStringAsFixed(2)}');
log('roundToDouble: $price: ${(price - _priceRemainder).toStringAsFixed(2)}');
}
log('-----------------------');
}
Debug console:
[log] price: 10.91, count: 0.05
[log] _price: 0.01
[log] _pricePlus: 5.00
[log] _someDiff > 2
[log] ceilToDouble: 10.91: 10.95
[log] floorToDouble: 10.91: 10.90
[log] roundToDouble: 10.91: 10.90
2
[log] -----------------------
[log] price: 10.91, count: 0.1
[log] _price: 0.01
[log] _pricePlus: 10.00
[log] _someDiff > 2
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.90
[log] roundToDouble: 10.91: 10.90
2
[log] -----------------------
[log] price: 10.91, count: 0.2
[log] _price: 0.11
[log] _pricePlus: 1.82
[log] _someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.80
[log] roundToDouble: 10.91: 11.00
2
[log] -----------------------
[log] price: 10.91, count: 0.25
[log] _price: 0.16
[log] _pricePlus: 1.56
[log] _someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.75
[log] roundToDouble: 10.91: 11.00
2
[log] -----------------------
[log] price: 10.91, count: 0.5
[log] _price: 0.41
[log] _pricePlus: 1.22
[log] _someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.50
[log] roundToDouble: 10.91: 11.00
2
[log] -----------------------
[log] price: 10.91, count: 1.0
[log] _price: 0.91
[log] _pricePlus: 1.10
[log] _someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.00
[log] roundToDouble: 10.91: 11.00
2
[log] -----------------------
[log] price: 10.91, count: 10.0
[log] _price: 0.91
[log] _pricePlus: 10.99
[log] _someDiff > 2
[log] ceilToDouble: 10.91: 20.00
[log] floorToDouble: 10.91: 10.00
[log] roundToDouble: 10.91: 10.00
If you need proper rounding (up when first digit is 5) and you want to have trailing 0's you can use this method:
import 'dart:math';
String customRound(double val, int places) {
num mod = pow(10.0, places);
return ((val * mod).round().toDouble() / mod).toStringAsFixed(places);
}
customRound(2.345) // -> 2.35
customRound(2.500) // -> 2.50
This DART rounding problem has been a long time coming (#LucasMeadows), since it's clear that it has not been adequately solved (as indicated by #DeepShah's observation) until now.
The well-known rounding rule (the unsolved problem):
" Rounding numbers that end with the number 5: round up if the result is an even number; round down if the result is an odd number. "
So here is the DART code solution:
double roundAccurately(double numToRound, int decimals) {
// Step 1 - Prime IMPORTANT Function Parameters ...
int iCutIndex = 0;
String sDeciClipdNTR = "";
num nMod = pow(10.0, decimals);
String sNTR = numToRound.toString();
int iLastDigitNTR = 0, i2ndLastDigitNTR = 0;
debugPrint("Round => $numToRound to $decimals Decimal ${(decimals == 1) ? "Place" : "Places"} !!"); // Deactivate this 'print()' line in production code !!
// Step 2 - Calculate Decimal Cut Index (i.e. string cut length) ...
int iDeciPlaces = (decimals + 2);
if (sNTR.contains('.')) {
iCutIndex = sNTR.indexOf('.') + iDeciPlaces;
} else {
sNTR = sNTR + '.';
iCutIndex = sNTR.indexOf('.') + iDeciPlaces;
}
// Step 3 - Cut input double to length of requested Decimal Places ...
if (iCutIndex > sNTR.length) { // Check that decimal cutting is possible ...
sNTR = sNTR + ("0" * iDeciPlaces); // ... and fix (lengthen) the input double if it is too short.
sDeciClipdNTR = sNTR.substring(0, iCutIndex); // ... then cut string at indicated 'iCutIndex' !!
} else {
sDeciClipdNTR = sNTR.substring(0, iCutIndex); // Cut string at indicated 'iCutIndex' !!
}
// Step 4 - Extract the Last and 2nd Last digits of the cut input double.
int iLenSDCNTR = sDeciClipdNTR.length;
iLastDigitNTR = int.parse(sDeciClipdNTR.substring(iLenSDCNTR - 1)); // Extract the last digit !!
(decimals == 0)
? i2ndLastDigitNTR = int.parse(sDeciClipdNTR.substring(iLenSDCNTR - 3, iLenSDCNTR - 2))
: i2ndLastDigitNTR = int.parse(sDeciClipdNTR.substring(iLenSDCNTR - 2, iLenSDCNTR - 1));
// Step 5 - Execute the FINAL (Accurate) Rounding Process on the cut input double.
double dAccuRound = 0;
if (iLastDigitNTR == 5 && ((i2ndLastDigitNTR + 1) % 2 != 0)) {
dAccuRound = double.parse(sDeciClipdNTR.substring(0, iLenSDCNTR - 1));
} else {
if (iLastDigitNTR < 5) {
dAccuRound = double.parse(sDeciClipdNTR.substring(0, iLenSDCNTR - 1));
} else {
if (decimals == 0) {
sDeciClipdNTR = sNTR.substring(0, iCutIndex - 2);
dAccuRound = double.parse(sDeciClipdNTR) + 1; // Finally - Round UP !!
} else {
double dModUnit = 1 / nMod;
sDeciClipdNTR = sNTR.substring(0, iCutIndex - 1);
dAccuRound = double.parse(sDeciClipdNTR) + dModUnit; // Finally - Round UP !!
}
}
}
// Step 6 - Run final QUALITY CHECK !!
double dResFin = double.parse(dAccuRound.toStringAsFixed(decimals));
// Step 7 - Return result to function call ...
debugPrint("Result (AccuRound) => $dResFin !!"); // Deactivate this 'print()' line in production code !!
return dResFin;
}
It's a completely manual approach (and probably a bit of an overkill), but it works. Please test it (to exhaustion) and let me know if I've missed the mark.
This function you can call to get degree of precision in dark(flutter).
double eval -> double that want to convert
int i -> number of decimal point to return.
double doubleToPrecision(double eval, int i) {
double step1 = eval;//1/3
print(step1); // 0.3333333333333333
String step2 = step1.toStringAsFixed(2);
print(step2); // 0.33
double step3 = double.parse(step2);
print(step3); // 0.33
eval = step3;
return eval; }
I prever converting my like this =>
`
num.tryParse("23.123456789")!.toDouble().roundToDouble()
`
This works pretty well
var price=99.012334554
price = price.roundTodouble();
print(price); // 99.01

Resources