Calculate result based on percentage in Powershell - powershell

I want to calculate the following in Powershell
$x = 100
$y = 25
result = x * y%
Should be really simple, but I can't seem to come up with the right way to calculate the correct result in Powershell

Divide by 100 to get the percentage:
$x = 100
$y = 25
$result = $x * ($y / 100)

Related

Multiply ffprobe fps as value in powershell

I'm trying to print the multiplied fps of a video with ffprobe,
.\ffprobe.exe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=avg_frame_rate -i "$videopath" > rate 2>&1
$script:rate = [IO.File]::ReadAllText(".\rate")
$script:framerate = ($rate/2)
echo "Multiplied = "$framerate
What this is supposed to do is to write the fps into a file, which ffprobe does as a fraction (1/10 in this case), and then multiply it by 2.
Since the variable is read as literal text I can't multiply it by 2, and instead it just gives me this.
Multiplied =
1/10
1/10
Is there any way to make it print Multiplied = 20 instead
Powershell doesn't understand fractions, so you'll need to convert the string into numbers and then do the math.
$rate = "1/10";
# convert the string into numbers
$parts = $rate.Split("/"); # #( "1", "10")
$numerator = [int] $parts[0]; # 1
$denominator = [int] $parts[1]; # 10
# do the math
$framerate = $denominator * 2; # 20
write-host "Multiplied = $framerate"
# Multiplied = 20

Calculate two audio duration with frame

I am stuck, I need a small logic.
I have two audio durations
x = "00:00:07:18"
y = "00:00:06:00" H : M: S: F
Answer should be x + y = 00:00:13:18
H=hours S= seconds M=minutes F=frame
My question is
if x = "00:00:03:14"
y = "00:00:13:18"
answer should be x + y = **00:00:17:02**
If the frame is greater than 30 it should increase 1 in second.
I am using power shell. How can I determine the logic to calculate both of this?
Calculation of the first 3 parts (hour:minute:second), we can offload to the [timespan] type, then all we need to worry about is carrying excess frames over:
# Simple helper function to turn our input strings into a [timespan] + frame count
function Parse-FrameDuration
{
param(
[string]$Duration
)
$hour,$minute,$second,$frame = ($Duration -split ':') -as [int[]]
[PSCustomObject]#{
Time = New-TimeSpan -Hours $hour -Minutes $minute -Seconds $second
Frame = $frame
}
}
# function to do the actual calculation
function Add-Frame
{
param(
[string]$Base,
[string]$Offset
)
# Parse our two timestamps
$a = Parse-FrameDuration $Base
$b = Parse-FrameDuration $Offset
# Calculate frames % frame rate, remember to carry any excess seconds
$frames = 0
$carry = [math]::DivRem($a.Frame + $b.Frame , 30, [ref]$frames)
# Calculate time difference, add any extra second carried from frame count
$new = ($a.Time + $b.Time).Add($(New-TimeSpan -Seconds $carry))
# Stitch output string together from new timespan + remaining frames
return "{0:hh\:mm\:ss}:{1:00}" -f $new,$frames
}
Now we can do:
PS C:\> Add-Frame -Base 00:00:03:14 -Offset 00:00:13:18
00:00:17:02

How to create a script that would calculate the difference between samples in a list?

I am trying to create a script that would calculate the difference between samples in a list.
If we take this example:
- result1 = 33
- result2 = 45
- result3 = 66
- result4 = 47
- result"n" = 50
The calculus should start at the second result from the list and descend until the last result, and then sum up those results:
result2 - result1 = 12,
result3 - result2 = 21,
result4 - result3 = 19,
result"n" - result4= 3
sum = 12 + 21 + 19 + 3 = 55
I am new at scripting, and so far i only came up with this solution:
$numbers
$1=[math]::abs($numbers[0]-$numbers[1])
$2=[math]::abs($numbers[1]-$numbers[2])
$3=[math]::abs($numbers[2]-$numbers[3])
$4=[math]::abs($numbers[3]-$numbers[4])
write-host "the results = $1, $2, $3, $4"
$sum = $1 + $2 + $3 + $4
The problem is that the list is dynamic and changes in length, one time there are 10 results and one time 20 for example.
I found a similar question here, but i don't know how to implement the solution to my case, as that is too complicated for me.
What you need is a For loop. It is structured as such:
For(<initial declaration, usually a start point like $i = 0>; <Condition to stop when false>;<Action to perform on each iteration to progress loop>){
Code to perform on each loop
}
For you we would do something like:
For($i=1;$i -le $numbers.count;$i++)
That starts 1, and since arrays start at 0 this will get you going with the second record. Then in the scriptblock we do something like:
{
[array]$Results += [math]::abs($numbers[$i] - $numbers[($i-1)])
}
That will get the differences for you, then to display them you can do something like:
"the results = " + ($Results -join ", ")
$sum = $Results|Measure -sum|select -expand Sum
So you put that all together and get
For($i=1;$i -le $numbers.count;$i++){
[array]$Results += [math]::abs($numbers[$i] - $numbers[($i-1)])
}
"the results = " + ($Results -join ", ")
$sum = $Results|Measure -sum|select -expand Sum
Use a for loop, use the length of your $numbers array to know when to stop.
$numbers = #(33,45,66,47,50)
$sum = 0
for($cur=1;$cur -lt $numbers.Length; $cur += 1){
$sum += [math]::abs($numbers[$cur]-$numbers[$cur-1]);
}
$sum

Converting numbers to K/M/G/T and days/hours/min?

Is there an easy way to convert numbers like these
123 -> 123B
1234 -> 1.2K
12345 -> 12.2K
123456 -> 123.4K
1234567 -> 1.2M
12345678 -> 12.3M
123456789 -> 123.4M
...
and ideally also large numbers into days/hours/min. ?
This was discussed on Stackoverflow using Time::Piece. One of the answers comes close to calculating days hours minutes. From what I've read about this question before, I think you can easily code it up like this:
sub dhms {
my $seconds = shift;
my $days = int $seconds / 86400;
$seconds %= 86400;
my $hours = int $seconds / 3600;
$seconds %= 3600;
my $mins = int $seconds / 60;
my $secs = $seconds % 60;
return $days, $hours, $mins, $secs;
}
Update: daxim's answer using DateTime::Format::Duration does this as well
Suffixing is quite simple actually, once we understand the relationship between the letters K, M, G, T and the factors they present:
K = 10^3 = 10^3^1
M = 10^6 = 10^3^2
G = 10^9 = 10^3^3
T = 10^12 = 10^3^4
The next important thing to realize is that 10^0 = 1.
We want to select the largest suffix whose value is smaller than the value we want to transform. To do that, we put the suffixes into an array:
my #suffixes = qw/ B K M G T /;
so that
$suffixes[$i] == 10**3**$i # conceptually
Now it's just a matter of looping over the indices (probably in reverse) and stopping as soon as the $val >= 10**3**$i.

Perl recursion help

I'm trying to write a program that will calculate the dividends of stocks. I did this without a subroutine. Right now, I'm trying to modify it so it can run using a recursive routine. Any help with this? Because I'm not so good at this.
Here's the original script + a pathetic attempt.
print "A stock xyz's price is now $100. It has 3.78% dividend. You have 1000 of it and reinvest the dividend into the stock.\n";
my %hash;
#stocknum = 1000;
#dividend = 6780;
while ($#dividend != 20) {
$a = $dividend[-1];
$stock = $stocknum[-1];
$div_total= $stock*100*0.0678;
$stock_total = $stock + int($a/100);
push (#stocknum, $stock_total);
push (#dividend, $div_total);
if ($#dividend == 20) {
last;
}
}
shift (#dividend);
$stock_num = $stocknum[-1];
$div = $stock_num*100*0.0678;
push (#dividend, $div);
#hash{#stocknum} = #dividend;
foreach $key(sort keys %hash) {
print "Stock number: $key\t"."Dividend: $hash{$key}\n";
}
$dividend=0.0378;
I don't think you want recursion. I think you just want to loop over the number of cycles of payouts that you're after. It looks like you're getting all mixed up with arrays for some reason.
print <<'HERE';
A stock xyz's price is now $100. It has 6.78% dividend.
You have 1000 of it and reinvest the dividend into the stock.
HERE
my $shares = 1000;
my $price = 100;
my $dividend = 6.78 / 100;
my $cycles = $ARGV[0] || 20;
foreach ( 1 .. $cycles ) {
local $cycle = $_;
local $payout = $shares * $dividend * $price;
local $new_shares = $payout / $price;
write();
$shares += $new_shares;
}
format STDOUT =
#### #####.###### ######.####### ###.###### #####.######
$cycle, $shares, $payout, $new_shares, $shares+$new_shares,
.
format STDOUT_TOP =
###.####%
$dividend
Cycle Shares Payout New Shares Total Shares
----------------------------------------------------------------
.
This gives me the output:
A stock xyz's price is now $100. It has 6.78% dividend.
You have 1000 of it and reinvest the dividend into the stock.
0.0678%
Cycle Shares Payout New Shares Total Shares
----------------------------------------------------------------
1 1000.000000 6780.0000000 67.800000 1067.800000
2 1067.800000 7239.6840000 72.396840 1140.196840
3 1140.196840 7730.5345752 77.305346 1217.502186
4 1217.502186 8254.6648194 82.546648 1300.048834
5 1300.048834 8814.3310942 88.143311 1388.192145
6 1388.192145 9411.9427423 94.119427 1482.311572
7 1482.311572 10050.0724603 100.500725 1582.812297
8 1582.812297 10731.4673731 107.314674 1690.126971
9 1690.126971 11459.0608610 114.590609 1804.717579
10 1804.717579 12235.9851873 122.359852 1927.077431
11 1927.077431 13065.5849830 130.655850 2057.733281
12 2057.733281 13951.4316449 139.514316 2197.247597
13 2197.247597 14897.3387104 148.973387 2346.220985
14 2346.220985 15907.3782750 159.073783 2505.294767
15 2505.294767 16985.8985220 169.858985 2675.153752
16 2675.153752 18137.5424418 181.375424 2856.529177
17 2856.529177 19367.2678194 193.672678 3050.201855
18 3050.201855 20680.3685775 206.803686 3257.005541
19 3257.005541 22082.4975671 220.824976 3477.830517
20 3477.830517 23579.6909021 235.796909 3713.627426
Don't worry about my use of format; I've had that on the brain this weekend since I rewrote some perlfaq stuff about it then also turned it into Use formats to create paginated, plaintext reports. You could just as easily created the output with printf:
print <<'HERE';
A stock xyz's price is now $100. It has 6.78% dividend.
You have 1000 of it and reinvest the dividend into the stock.
Cycle Shares Payout New Shares Total Shares
----------------------------------------------------------------
HERE
my $shares = 1000;
my $price = 100;
my $dividend = 6.78 / 100;
my $cycles = $ARGV[0] || 20;
foreach ( 1 .. $cycles ) {
my $payout = $shares * $dividend * $price;
my $new_shares = $payout / $price;
printf "%4d %12.6f %12.6f %10.6f %12.6f\n",
$_, $shares, $payout, $new_shares, $shares + $new_shares;
$shares += $new_shares;
}
As a side note, you really don't ever want recursion, and especially not in Perl if you can help it. Other languages get away with it because they know how to unroll your recursion to turn it into an iterative process. Perl, being a dynamic language, can't really do that because it doesn't know if the subroutine will have the same definition on the next go around. It's nice as a computer science topic because it makes the programming marginally easier and they know it all works out in the end. I think I talk about this in Mastering Perl somewhere, but Mark Jason Dominus covers it extensively in Higher-Order Perl. Basically, instead of recursion you use a queue, which is a better skill to practice anyway.