I try to calculate the price for a meterID that has scaled rates . I use this
as guide for the algorithm ( public static double computeRatedUsagePerMeter(Dictionary rates, double usage) )
https://github.com/PartnerCenterSamples/Commerce-API-DotNet/blob/master/Usage.cs
Comparing with the price from azure pricing calculator if i ask the price for quantity X in calculator it is equal to the price that i calculate from the above method but for quantity X - 1.
So i am confused if the method provided from Microsoft is complete or not , or maybe just a hint for the right direction.
private static decimal computeRatedUsagePerMeter(Dictionary<decimal, decimal> rates, decimal usage)
{
decimal total = Decimal.Zero;
if (rates.Count == 0)
return Decimal.Zero;
else if (rates.Count == 1)
return (usage * rates.Values.FirstOrDefault());
var remainingUsage = usage;
while (rates.Count > 0)
{
decimal LastKey = rates.Keys.Last();
if (remainingUsage > LastKey)
{
decimal LastKeyValue = Decimal.Zero;
if (rates.TryGetValue(LastKey, out LastKeyValue))
{
total = total + ((remainingUsage - LastKey + 1) * LastKeyValue); // remainingUsage - LastKey +1 because tiered pricing is exclusive
remainingUsage = LastKey - 1;
}
rates.Remove(LastKey);
}
else if (remainingUsage <= LastKey)
{
rates.Remove(LastKey);
}
}
return total;
}
{
"MeterId": "d23a5753-ff85-4ddf-af28-8cc5cf2d3882",
"MeterName": "Standard IO - Page Blob/Disk (GB)",
"MeterCategory": "Storage",
"MeterSubCategory": "Locally Redundant",
"Unit": "GB",
"MeterTags": [],
"MeterRegion": "",
"MeterRates": {
"0": 0.042165,
"1024": 0.0421650,
"51200": 0.0421650,
"512000": 0.0421650,
"1024000": 0.0379485,
"5120000": 0.0312021
},
"EffectiveDate": "2014-02-01T00:00:00Z",
"IncludedQuantity": 0.0
}
According to the method provided by the link above the price for quantity 1 = 0.084330 while azure pricing calculator gives 0.04
( the prices are in EUR )
And another example : les say 100 quantity.
method: 4.258665 EUR
Azure Calculator = 4.22 EUR
method for 99 quantity = 4.216500 which rounded is 4.22 EUR.
Also cannot check the prices < 1.00 lets say 0.5 quantity ( in this case its measured in GB so 0,5 GB is perfectly reasonable quantity ) cause pricing calculator doesn't allow decimal .
According to the method provided by the link above the price for
quantity 1 = 0.084330 while azure pricing calculator gives 0.04 ( the
prices are in EUR )
Looking at the code above, I believe there's an issue in the code itself. Essentially you're trying to find the price for 1 GB of storage which would fall under 0 - 1023 range or in other words the value of LastKey is 0. So when the following code executes:
total = total + ((remainingUsage - LastKey + 1) * LastKeyValue);
it gives you a total of 0.084330 (0 + (1 - 0 + 1) * 0.042165).
Also cannot check the prices < 1.00 lets say 0.5 quantity ( in this
case its measured in GB so 0,5 GB is perfectly reasonable quantity )
cause pricing calculator doesn't allow decimal.
I am sure someone from Microsoft would provide a proper answer as to why they designed the calculator the way it is designed.
Related
Example 1:
``
Given S="300.01" and B-["300.00", "200.00*,*100.00"].
R[0]="150.00" (=300.01 300.00/600.00) R[1]="100.00" (=150.01* 200.00/300.00)
R[2]="50.01" (=50.01*100.00/100.00)
Example 2 (Pay careful attention to this one).
Given S="1.00" and B=["0.05","1.00"]. 1. First we consider 1.00 because it is the largest,
a. 1.00*1.00/1.05~0.95238...
b. Round 0.95238... to "0.95". Rounding down to carry pennies to smaller departments. c. Set R[1]=0.95. Notice, this is in the same place as 1.00. It is the 2nd value in the result! 2. Now we have 0.05 left
Next we look at the smaller B[0]=0.05 department
a. 0.05 0.05/0.05 = 0.05 b. No rounding required
c. Set R[0]=0.05. R=["0.05", "0.95"]
`
Write a function:
class Solution { public String[] solution(String 5, String[] B); }
that, given a string S representing the total excess billables and an array B consisting of K strings representing the undiscounted bills for each customer. The return value should be an array of strings R (length M) in the same order as B representing the amount of the discount to each customer.
Notes:
The total S should be completely refunded. Neither more nor less than S should be
returned. Don't lose or gain a penny!
Be careful with the types you choose to represent currencies. Floating points numbers are notoriously error prone for precise calculations with currencies.
Test Output
Amounts should be rounded down to the nearest $0.01. By design, fractional pennies are pushed to groups with smaller unadjusted invoices.
Results should be represented with 2 decimal places of precision as strings, even if these are both zeroes. ex. "100.00" 5. You may assume sensible inputs. The total to be discounted will never exceed the total of the
unadjusted invoices.
Please do pay attention to returning the discounts in the same order as the incoming invoices.
Answer:::
def solution(A):
answer = 0
current_sum = 0
#Currently there is one empty subarray with sum 0
prefixSumCount = {0:1}
for list_element in A:
current_sum = current_sum + list_element
if current_sum in prefixSumCount:
answer = answer + prefixSumCount[current_sum]
if current_sum not in prefixSumCount:
prefixSumCount[current_sum] = 1
else:
prefixSumCount[current_sum] = prefixSumCount[current_sum] + 1
if answer > 1000000000:
return -1
else:
return answer
#Sample run
A = [2,-2,3,0,4,-7]
print(solution(A))
strong text
Find my solution for JavaScript
You can avoid function sumArray and use the sum funciton with reducer within solution function.
enter code here
function solution(S, B) {
// write your code in JavaScript (Node.js 8.9.4)
let copyArray=[...B];
let solutionObj={};
//ordered array to consider last first
copyArray.sort();
//calculating sum of values within array
let sumArray=B.reduce((acc,value)=> acc+Number(value),0);
//calculating values of array
//loop for ading on to solvin array
let initial=S;
for(i=copyArray.length-1;i>=0;i--){
//obtaining index of value addded to solution array
let index=B.indexOf(copyArray[i]);
let value=initial*copyArray[i]/sumArray;
value=i==0?Math.ceil(value*100)/100:Math.floor(value*100)/100;
solutionObj[index]=value.toFixed(2);
}
return Object.values(solutionObj) ;
}
console.log(solution(300.01,["300.00","200.00","100.00"]))
console.log(solution(1.00,["0.05","1.00"]))
These are the resulting entries
Solution in java for the same coding exercise
public String[] solution(String S, String[] B) {
List<Double> list = Arrays.stream(B).sorted(Comparator.comparingDouble(v->Double.valueOf((String) v)).reversed()).map(Double::parseDouble).collect(Collectors.toList());
Double S1 = Double.valueOf(S);
String R[] = new String[B.length];
Double total = 0.00;
for (int i = 0; i< list.size(); i++){
Double individualValue = list.get(i);
Double sumTotal = 0.0;
for(int j = i+1;j < list.size(); j++){
sumTotal+=list.get(j);
}
BigDecimal data = new BigDecimal(S1 * (individualValue / (individualValue + sumTotal)));
data = data.setScale(2, RoundingMode.FLOOR);
total+=data.doubleValue();
R[i] = String.valueOf(data);
S1 = S1 - Double.valueOf(R[i]);
}
Double diff = new BigDecimal(Double.valueOf(S) - total).setScale(2, RoundingMode.HALF_DOWN).doubleValue();
if (diff > 0) {
R[B.length - 1] = String.valueOf(Double.valueOf(R[B.length - 1]) + diff);
}
return R;
}
I have a problem and i need your help!
Here is the code:
kg_lemons = float(input())
kg_sugar = float(input())
water = float(input())
total_lemon_juice = kg_lemons * 980 #in mililiters need to multiply by 1000
total_lemonade = total_lemon_juice + 5 * 1000 + (0.3 * kg_sugar)
cups_made = total_lemonade / 150
money_made = cups_made * 1.20
print(f'All cups sold: {cups_made:.2f}')
print(f'Money earned: {money_made:.2f}')
At then end, after I print it, it must shown the numbers:
All cups sold: 66
Money earned: 79.20
But I got:
All cups sold: 66.01
Money earned: 79.21
So I need to round it up to the second decimal (the lowest number). Should I use math.floor and, if so, how?
This is the code:
amount_borrowed = float(input("Amount borrowed: $"))
interest_rate = float(input("Interest rate: "))
loan_length = int(input("Length of loan (months): "))
i = interest_rate/100
monthly_payment1 = (i / 12) * amount_borrowed #this is the first part of the payment formula
monthly_payment2 = monthly_payment1 / 1 - (1 + i / 12)**-loan_length
#second part of monthly payment formula
print("The monthly payment is ${:.2f}" .format(monthly_payment2))
I should get this output:
Amount borrowed: $100.00
Interest rate: 10.0
Length of loan (months): 12
The monthly payment is $8.79.
I keep on getting this:
Amount borrowed: $100
Interest rate: 10
Length of loan (months): 12
The monthly payment is $-0.07
Don't make much sense divide by 1. I think that you did forget a pair of parentheses in the denominator of the division. So, the following line
monthly_payment2 = monthly_payment1 / 1 - (1 + i / 12)**-loan_length
should be
monthly_payment2 = monthly_payment1 / (1 - (1 + i / 12)**-loan_length)
I tested here and get the expect value of $8.79
Azure Rate Card API returns a MeterRates field (see documentation).
Azure UsageAggregate gives a quantity (see documentation).
According to the azure support page. This is the forum to ask questions.
So, how are meter rates applied?
Example meter rates:
{"0":20, "100":15, "200":10}
If I have a quantity of 175 is the amount 100*20 + 75*15 or 175*15?
Why specify an included quantity?
Example: rates:{"0":23} with included quantitiy 10 could be expressed as rates:
{"0":0, "10":23}
example meter rates: {"0":20, "100":15, "200":10}
if I have a quantity of 175 is the amount 100*20 + 75*15 or 175*15 ?
The pricing is tiered pricing. So when you get the rates it essentially tells you that:
from 0 - 99 units, the unit rate is 20
from 100 - 199 units, the unit rate is 15
from 200 units and above, the unit rate is 10
Based on this logic, your calculation should be:
99 * 20 + 75 * 15 = 3105
One thing which confuses me though is the upper limit. Above calculation is based on the information I received from Azure Billing team. What confused me is what would happen if the consumption is say 99.5 units? For the first 99 units it is fine but I am not sure how the additional 0.5 units will be calculated.
Guarav gets at the core of the issue and is why I marked it as the answer. Based on that I devised the following code to implement the logic. It falls in two parts:
Creating a bucket list from the meter rates
Processing a quantity with the bucket list to determine an amount
The following function creates a list of buckets (each bucket object is a simple POCO with Min, Max and Rate properties). The list is attached to a meter object that has the other properties from the rate card api.
private Dictionary<int, RateBucket> ParseRateBuckets(string rates)
{
dynamic dRates = JsonConvert.DeserializeObject(rates);
var rateContainer = (JContainer)dRates;
var buckets = new Dictionary<int, RateBucket>();
var bucketNumber = 0;
foreach (var jToken in rateContainer.Children())
{
var jProperty = jToken as JProperty;
if (jProperty != null)
{
var bucket = new RateBucket
{
Min = Convert.ToDouble(jProperty.Name),
Rate = Convert.ToDouble(jProperty.Value.ToString())
};
if (bucketNumber > 0)
buckets[bucketNumber - 1].Max = bucket.Min;
buckets.Add(bucketNumber, bucket);
}
bucketNumber++;
}
return buckets;
}
The second function uses the meter object with two useful properties: the bucket list, and the included quantity. According to the rate card documentation (as I read it) you don't start counting billable quantity until after you surpass the included quantity. I'm sure there's some refactoring that could be done here, but the ordered processing of the buckets is the key point.
I think I've addressed issue on the quantity by recognizing that it's a double and not an integer. Therefore the quantity associated with any single bucket is the difference between the bucket max and the bucket min (unless we've only filled a partial bucket).
private double CalculateUsageCost(RateCardMeter meter, double quantity)
{
var amount = 0.0;
quantity -= meter.IncludedQuantity;
if (quantity > 0)
{
for (var i = 0; i < meter.RateBuckets.Count; i++)
{
var bucket = meter.RateBuckets[i];
if (quantity > bucket.Min)
{
if (bucket.Max.HasValue && quantity > bucket.Max)
amount += (bucket.Max.Value - bucket.Min)*bucket.Rate;
else
amount += (quantity - bucket.Min)*bucket.Rate;
}
}
}
return amount;
}
Finally, the documentation is unclear about the time scope for the tiers. If I get a discounted price based on quantity, over what time scope do I aggregate quantity? The usage api allows me to pull data either daily or hourly. I want to pull my data hourly so I can correlate my costs by time of day. But when is it appropriate to actually calculate the bill? Seems like hourly is wrong, daily may work, but it might only be appropriate over the entire month.
Recently I just did this similar task. Following is my example (I think you can use regex to remove those characters rather than like me using replace). The first function parse the rate info string to generate a key-value pair collection, and the second function is used to calculate the total price.
private Dictionary<float, double> GetRatesDetail(string r)
{
Dictionary<float, double> pairs = null;
if(string.IsNullOrEmpty(r) || r.Length <=2)
{
pairs = new Dictionary<float, double>();
pairs.Add(0, 0);
}
else
{
pairs = r.Replace("{", "").Replace("}", "").Split(',')
.Select(value => value.Split(':'))
.ToDictionary(pair => float.Parse(pair[0].Replace("\"", "")), pair => double.Parse(pair[1]));
}
return pairs;
}
public decimal Process(Dictionary<float, double> rates, decimal quantity)
{
double ret = 0;
foreach (int key in rates.Keys.OrderByDescending(k => k))
{
if (quantity >= key)
{
ret += ((double)quantity - key) * rates[key];
quantity = key;
}
}
return (decimal)ret;
}
I am having one price calculation code in C#.There is particular sequence of calculating all the prices and taxes.how to apply fuzzy logic so that I will get related search of that particular price.That means if one of tax name is 'cost/kg'.So I should get all the names of taxes or prices which start from C or CO.
A simple way would be getting prices within some min/max bounds of what has been searched
double k = 0.1;
double min = searchedAmount - (searchedAmount * k);
double max = searchedAmount + (searchedAmount * k);
var results = products.Where(p => p.Price >= min && p.Price <= max);