On Sat, Oct 08, 2016 at 12:58:00PM -0400, Patrick 'P. J.' McDermott wrote:
> If you want the amount a project receives to be exactly equal to the
> amount a patron intends to donate, here's the math to determine the
> extra fee to add.
>
> Remember that Stripe's fee is 2.9% + $0.30, and begin with an equation
> that yields the final donation after fees ($0.30 less than 100%-2.9%
> of the payment):
> 
>     donation = total_payment * (1 - 0.029) - $0.30
> 
> Do some algebra, first adding $0.30 to both sides:
> 
>     donation + $0.30 = total_payment * (1 - 0.029)
> 
> And then divide both sides by 100%-2.9% to isolate total_payment and
> get a formula to calculate it:
> 
>                     donation + $0.30
>     total_payment = ----------------
>                        1 - 0.029

Awesome, thanks! I was caught up calculating the fee, but this way of
looking at it is easier to implement.

I spent some time trying to show that the rounding works out
analytically, but in the end I just brute-forced the calculation on
every possible value. It works (until integer truncation errors occur
up at $20M).

Plus, I made some cool graphs:
https://www.desmos.com/calculator/xtzs3n4lxq

So, I'll just go ahead with charging enough so that

    crowdmatch = net_transaction_balance

I don't really like the lack of an analytical solution, but I'm
satisfied that it actually works.

Brute force code attached.

-Bryan
import Data.Int

stripeFee :: Int32 -> Int32
stripeFee = round . (+ 30) . (* 0.029) . fromIntegral

payment :: Int32 -> Int32
payment = round . (/ (1 - 0.029)) . (+ 30) . fromIntegral

bad c =
    let p = payment c
        f = stripeFee p
    in p - f /= c

main = do
    putStr "First bad at: "
    print (take 1 (filter bad ([1..])))
#include <stdio.h>
#include <limits.h>
#include <math.h>

long int stripe_fee (int c) {
    return lrint(c * 0.029 + 30);
}

long int payment (int c) {
    return lrint( (c + 30) / (1 - 0.029) );
}

int test (long int c) {
    int p, f;
    p = payment(c);
    f = stripe_fee(p);
    return (p - f) != c;
}

int main () {
    long int i = 0;
    int max = INT_MAX;
    for (i = 0; i < max; i++) {
        if (test(i)) {
            printf("First error at %ld\n", i);
            return 0;
        }
    }
}

Attachment: signature.asc
Description: Digital signature

_______________________________________________
Discuss mailing list
Discuss@lists.snowdrift.coop
https://lists.snowdrift.coop/mailman/listinfo/discuss

Reply via email to