division calculates a wrong value

4 次查看(过去 30 天)
I have this Market class which adjusts the price of two cryptocurrencies. This method allows you to buy the first cryptocurrency by selling the second.
tokenBobtained = abs(obj.supplyB - (obj.k / obj.supplyA));
disp(tokenBobtained) % print 182
obj.supplyB = obj.k / obj.supplyA;
obj.priceB = (transactionVolume * obj.priceA) / tokenBobtained; % ERROR!
tokenBobtained in the example is 182, but in the last line the result of obj.priceB is not the one hoped for.
obj.priceB in the end of execution is 1 but it should be 0.55. The cool thing is that if I replace 182 with "tokenBobtained" in the last line I get 0.55, but in this way it doesn't work! What's the problem?
  3 个评论
Walter Roberson
Walter Roberson 2023-5-24
Are any of the fields involved integer data type, such as uint16 ?
Francesco Pio
Francesco Pio 2023-5-24
移动:Walter Roberson 2023-5-24
Ok sorry, this is the Cryptocurrency class. It simply has a property representing price and a constant property representing the initial amount of money in circulation.
% cryptocurrency is a class whose objects represent cryptocurrencies
classdef Cryptocurrency
properties (GetAccess = public, SetAccess = {?Market})
price (1,1) double {mustBeNonnegative} = 0
end
properties (GetAccess = public, SetAccess = immutable)
initialSupply (1,1) uint64 {mustBePositive} = 1
end
methods
% Constructor
function obj = Cryptocurrency(inputPrice, inputSupply)
obj.price = inputPrice;
obj.initialSupply = inputSupply;
end
end
end
after that, the Market class takes two cryptocurrencies as input.
This class has the task of regulating the price of the two coins. It allows you to buy/sell one cryptocurrency while selling/buying the other. The price is adjusted by simulating an automated market maker, but these are technical details.
classdef Market
% assetA and assetB are the two cryptocurrencies taken as input
% supplyA and supplyB represent the amount of money in the "pool".
properties (GetAccess = public, SetAccess = private)
assetA (1,1) Cryptocurrency = Cryptocurrency(1,1)
assetB (1,1) Cryptocurrency = Cryptocurrency(1,1)
priceA (1,1) double
priceB (1,1) double
supplyA (1,1) double {mustBeNonnegative} = 0
supplyB (1,1) double {mustBeNonnegative} = 0
end
% k is a constant used to adjust the price and depends on the initial supply of tokens A and B.
properties (GetAccess = public, SetAccess = immutable)
k (1,1) uint64 {mustBePositive} = 1
end
methods
% Constructor
function obj = Market(cryptoA, cryptoB)
arguments (Input)
cryptoA (1,1) Cryptocurrency
cryptoB (1,1) Cryptocurrency
end
obj.assetA = cryptoA;
obj.assetB = cryptoB;
% formula used in automated market makers
obj.k = cryptoA.initialSupply * cryptoB.initialSupply;
% la supply nell'AMM non è uguale a quella della crypto nel
% mercato.
obj.supplyA = cryptoA.initialSupply;
obj.supplyB = cryptoB.initialSupply;
obj.priceA = cryptoA.price;
obj.priceB = cryptoB.price;
end
% function that allows you to buy assetA and sell assetB.
% to buy assetA you have to put assetB in the pool. In this way in
% the pool there will be more assetB (therefore its price decreases) and less assetA
% (therefore its price increases being rarer).
% transactionVolume is the number of assetA bought.
function obj = buyCryptoA(obj, transactionVolume)
arguments (Input)
obj (1,1) Market
transactionVolume (1,1) double {mustBeNonnegative}
end
% I cannot buy more crypto than there is in the pool
if transactionVolume >= obj.supplyA
disp("Non è possibile eseguire la transazione.")
else
% the amount of token A decreases
obj.supplyA = obj.supplyA - transactionVolume;
% The amount of token B varies so that k remains constant
% tokenBsold is the quantity of assetB sold to take assetA
tokenBsold = abs(obj.supplyB - (obj.k / obj.supplyA));
obj.supplyB = obj.k / obj.supplyA;
% change in the price of A
obj.priceA = tokenBsold * obj.priceB ...
/ transactionVolume;
% change in the price of B
obj.priceB = obj.priceA * transactionVolume ...
/ tokenBsold;
end
end
% function that allows you to sell assetA and buy assetB.
% works complementary to the previous method
% transactionVolume is the quantity of assetA sold.
function obj = sellCryptoA(obj, transactionVolume)
arguments (Input)
obj (1,1) Market
transactionVolume (1,1) double {mustBeNonnegative}
end
% the quantity of tokenA increases
obj.supplyA = obj.supplyA + transactionVolume;
% amount of tokenB obtained by selling x tokenA
tokenBobtained = abs(obj.supplyB - (obj.k / obj.supplyA));
disp(tokenBobtained)
% the amount of tokenB varies so that k remains constant
obj.supplyB = obj.k / obj.supplyA;
% change of price of tokenB
obj.priceB = (transactionVolume * obj.priceA) / tokenBobtained;
disp(obj.priceB)
% change of price of tokenA
obj.priceA = (obj.priceB * tokenBobtained) / transactionVolume;
end
end
Now I did that
a = Cryptocurrency(1, 1000);
b = Cryptocurrency(0.5, 2000);
m = Market(a,b);
m = m.sellCryptoA(100);
I obtain :
m =
Market with properties:
assetA: [1×1 Cryptocurrency]
assetB: [1×1 Cryptocurrency]
priceA: 2
priceB: 1
supplyA: 1100
supplyB: 1818
k: 2000000
SupplyA and supplyB is correct, but the problem is with prices that are wrong.
How I said, in the marketClass, method "sellCryptoA", tokenBobtained is is calculated correctly (it should be and is 182), but the priceA it is not calculated correctly.
obj.priceB = (transactionVolume * obj.priceA) / tokenBobtained;
Here, if I replace tokenBobtained with 182, i obtain the correct price (0.55), but if I use the variable (that contains 182), it doesnt work.

请先登录,再进行评论。

回答(1 个)

Walter Roberson
Walter Roberson 2023-5-24
移动:Walter Roberson 2023-5-24
initialSupply (1,1) uint64 {mustBePositive} = 1
Operations on uint64 return uint64.
Division with integer datatypes round before conversion to integer data type.
  2 个评论
Steven Lord
Steven Lord 2023-5-24
The k property of the Market class is uint64 and that gets used in the originally posted code.
You could convert those integer values to double before dividing with / or you could use the idivide function, which lets you control how the result is rounded. Though idivide does not allow you to perform the division between a double and a 64-bit integer so unless you need to allow values of k outside the range of a 32-bit integer I'd store that property as a uint32.
Francesco Pio
Francesco Pio 2023-5-25
Ok, thank you very much! Now this is printed:
m =
Market with properties:
assetA: [1×1 Cryptocurrency]
assetB: [1×1 Cryptocurrency]
priceA: 1
priceB: 0.5500
supplyA: 1100
supplyB: 1.8182e+03
k: 2000000
priceA is 1 but it should be 1.0001, how can i show all decimal digits?

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Logical 的更多信息

标签

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by