Handling decimals in somewhat complex mathHow to handle floating point number in Solidity?Decimals on ERC20 TokensCan you update contract token decimals and token name?Best practices for handling payment in smart contractsHow is a map initialised in memoryStoring complex data types in Eternal StorageSolidity Math: What's wrong with the functionHandling combinations without recursionHandling the String msg returned from revert() in solidityHow does delegatecall work from Solidity 0.5.0 onwards?Simple but important question: How to get the value of contract's state when using Metamask?

Managing libraries hosted on EmacsWiki

Does Lightning Network has concept of continuous stream of value?

Why does this sentence use 东西?

4 Layer PCB stack up

What LISP compilers and interpreters were available for 8-bit machines?

Why is the application of an oracle function not a measurement?

How hard would it be to convert a glider into an powered electric aircraft?

Select items in a list that contain criteria

Can a user sell my software (MIT license) without modification?

"Living" organ bank is it practical?

Company did not petition for visa in a timely manner. Is asking me to work from overseas, but wants me to take a paycut

Traffic law UK, pedestrians

Payment instructions from HomeAway look fishy to me

Do any instruments not produce overtones?

Why does VirtualBox crash macOS?

Why does NASA use higher frequencies even though they have worse Free Space Path Loss (FSPL)?

How to pass a regex when finding a directory path in bash?

Secure offsite backup, even in the case of hacker root access

How to retract the pitched idea from employer?

Building a road to escape Earth's gravity by making a pyramid on Antartica

Do manufacturers try make their components as close to ideal ones as possible?

Are go-arounds prohibited at St Barth (TFFJ)?

Does the "6 seconds per round" rule apply to speaking/roleplaying during combat situations?

SF novella separating the dumb majority from the intelligent part of mankind



Handling decimals in somewhat complex math


How to handle floating point number in Solidity?Decimals on ERC20 TokensCan you update contract token decimals and token name?Best practices for handling payment in smart contractsHow is a map initialised in memoryStoring complex data types in Eternal StorageSolidity Math: What's wrong with the functionHandling combinations without recursionHandling the String msg returned from revert() in solidityHow does delegatecall work from Solidity 0.5.0 onwards?Simple but important question: How to get the value of contract's state when using Metamask?













4















I'm a bit lost on what to do with the following calculation. The problem is that decimals are being round up/down, which obviously doesn't give me the result I desire.



int totalValue = 275000;
int percentage = 2;

for (uint i = 0; i < 30; i++)
totalValue += totalValue * percentage / 100;



With the above code, the result is:



498108


The expected result is:



498124.436


I know that normally you could simply use the following calculation to work with a predetermined amount of decimals like so:



value * 10**4 (4 decimals)


But I haven't gotten that to work in this case, often resulting in insanely high numbers due to the multiplication and division that "do not make sense" once I revert the above calculation using:



value / 10**4


Thank you very much for your time. Any help would be very much appreciated!










share|improve this question




























    4















    I'm a bit lost on what to do with the following calculation. The problem is that decimals are being round up/down, which obviously doesn't give me the result I desire.



    int totalValue = 275000;
    int percentage = 2;

    for (uint i = 0; i < 30; i++)
    totalValue += totalValue * percentage / 100;



    With the above code, the result is:



    498108


    The expected result is:



    498124.436


    I know that normally you could simply use the following calculation to work with a predetermined amount of decimals like so:



    value * 10**4 (4 decimals)


    But I haven't gotten that to work in this case, often resulting in insanely high numbers due to the multiplication and division that "do not make sense" once I revert the above calculation using:



    value / 10**4


    Thank you very much for your time. Any help would be very much appreciated!










    share|improve this question


























      4












      4








      4








      I'm a bit lost on what to do with the following calculation. The problem is that decimals are being round up/down, which obviously doesn't give me the result I desire.



      int totalValue = 275000;
      int percentage = 2;

      for (uint i = 0; i < 30; i++)
      totalValue += totalValue * percentage / 100;



      With the above code, the result is:



      498108


      The expected result is:



      498124.436


      I know that normally you could simply use the following calculation to work with a predetermined amount of decimals like so:



      value * 10**4 (4 decimals)


      But I haven't gotten that to work in this case, often resulting in insanely high numbers due to the multiplication and division that "do not make sense" once I revert the above calculation using:



      value / 10**4


      Thank you very much for your time. Any help would be very much appreciated!










      share|improve this question
















      I'm a bit lost on what to do with the following calculation. The problem is that decimals are being round up/down, which obviously doesn't give me the result I desire.



      int totalValue = 275000;
      int percentage = 2;

      for (uint i = 0; i < 30; i++)
      totalValue += totalValue * percentage / 100;



      With the above code, the result is:



      498108


      The expected result is:



      498124.436


      I know that normally you could simply use the following calculation to work with a predetermined amount of decimals like so:



      value * 10**4 (4 decimals)


      But I haven't gotten that to work in this case, often resulting in insanely high numbers due to the multiplication and division that "do not make sense" once I revert the above calculation using:



      value / 10**4


      Thank you very much for your time. Any help would be very much appreciated!







      solidity contract-development contract-design contract-debugging






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited May 20 at 11:50









      shane

      2,6224932




      2,6224932










      asked May 20 at 10:11









      NickNick

      1235




      1235




















          3 Answers
          3






          active

          oldest

          votes


















          4














          You need to multiply before calculations and divide after that:



          int decimals = 4;
          int totalValue = 275000;
          int percentage = 2;

          totalValue = totalValue * 10**decimals;
          for (uint i = 0; i < 30; i++)
          int AddValue = totalValue * percentage;
          AddValue = AddValue / 100;
          totalValue += AddValue;

          totalValue = totalValue / 10**decimals;


          EDIT: fixed line 5 and the percentage calculation
          EDIT2: Actually you don't need to multiply the percentage and will get better results - fixed






          share|improve this answer

























          • Thank you for your answer! I was working on a solution that was similar to this, but I can see where I went wrong in several places. On line 5 I think it's missing an assignment, right? Also I keep getting "275000" as output with this example, but I haven't figured out why

            – Nick
            May 20 at 13:49












          • Wont the line "percentage = percentage / (100 * 10**decimals);" also get truncated to 0?

            – Nick
            May 20 at 13:55






          • 1





            made several errors in a hurry ... should be fixed now

            – KNK
            May 20 at 14:39











          • Awesome, that seems to work! I'll validate it properly as soon as possible. One more question though. This function will still return a rounded number, right? So would it be better to take out the last line and account for the fact that the last 4 digits are decimals wherever I'm calling the backend from? -or am I doing something wrong?

            – Nick
            May 20 at 14:47






          • 1





            There are no floating point numbers in Solidity (yet), so the number as always rounded at the end, but yes you can return the number as is and divide in the client to get a floating point result

            – KNK
            May 20 at 14:58


















          6














          Generally speaking, in order to avoid data-loss (i.e., precision-loss) in an arithmetic computation, try to postpone every division as much as possible, without altering the expression.



          More specifically with regards to your code, it appears that you are trying to compute the result of applying compound interest: 275000 * 1.02 ** 30.



          You can do this very precisely in Solidity, by calculating (off-line) the exact value of 1.02 ** 30, and storing it scaled up to the level of precision that you desire.



          Moreover, you won't even need those 30 iterations in order to achieve all that, so you can optimize your code here for both accuracy and performance.



          For example:



          uint256 INTEREST_N = 181136158410335375505681049921897;
          uint256 INTEREST_D = 10000000000000000000000000000000;
          uint256 totalValue = 275000 * INTEREST_N / INTEREST_D;


          Of course, I'm aware of the fact that you most likely want the 275000 part as an input from the outside rather than a hard-coded value (in which case, you could just as well compute everything outside of the contract).



          But assuming that the number of iterations and the compound interest percentage are both constant (30 and 2% in your case), you can do it using the numerator and denominator described above.



          If either the number of iterations or the compound interest percentage is a variable, then instead of a single pair of numerator and denominator you can use an array of numerators and an array of denominators.



          If both the number of iterations and the compound interest percentage are variables, then instead of a pair of arrays you can use a pair of tables.






          share|improve this answer























          • I appreciate the answer and understand the gist of it, thank you! I'll come back to this solution once my understanding of the issue has improved.

            – Nick
            May 22 at 7:37







          • 1





            @Nick: NP. In your coding example, you could have simply used a constant (or two constants), so I suppose that this example does not represent what you're actually trying to achieve. As explained in my answer, I tend to guess that your intention is for one or more of these constants values (275000, 30 and 2%) to be an input variable. If you provide a description of the actual purpose, then I might be able to guide you through and suggest a scheme which will allow you to realize it while optimizing for both accuracy and performance (i.e., gas cost).

            – goodvibration
            May 22 at 7:42











          • That's awesome! In my case all three of those values are variables, so I figured I might as well send the result of 1.02**30 from the backend/caller. Also, the value of 275000 can contain decimals. At this point I'm not too sure how that will affect the calculation, but added "100000000000000000000000000000000 / (10**decimals);" to make the amount of decimals in the outcome variable.

            – Nick
            May 22 at 8:01












          • To add a more complete description of the variables with examples: the initial value (275000.5115 , max 4 decimals), interest rate (2.2152%, max 4 decimals) and amount of years (30, always a round number). To make it easier I can make sure there's always 4 decimals by padding zeroes.

            – Nick
            May 22 at 8:07












          • @Nick: Sorry, but in that case you can do the full calculation offline and just put the result hard-coded in your contract. There is no need for any code apart from that.

            – goodvibration
            May 22 at 9:37


















          2














          The reason you are getting the value 498108 is because Solidity truncates divided values.



          This means that if you divide 3/2, the result will be 1, not 1.5. Similarly, if you divide 11/3, the result will be 3, not 3.666.



          With this in mind, the reason you are getting that final result is because a few of the loop results are being truncated.






          share|improve this answer

























          • So you're saying that it's not possible in any way? I'm aware of what's happening (actually I thought it was rounding it down/up, but you're saying it's truncating. Thanks for letting me know!), but I don't know how else to approach this to get the result I want.

            – Nick
            May 20 at 13:02












          Your Answer








          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "642"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fethereum.stackexchange.com%2fquestions%2f70898%2fhandling-decimals-in-somewhat-complex-math%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          4














          You need to multiply before calculations and divide after that:



          int decimals = 4;
          int totalValue = 275000;
          int percentage = 2;

          totalValue = totalValue * 10**decimals;
          for (uint i = 0; i < 30; i++)
          int AddValue = totalValue * percentage;
          AddValue = AddValue / 100;
          totalValue += AddValue;

          totalValue = totalValue / 10**decimals;


          EDIT: fixed line 5 and the percentage calculation
          EDIT2: Actually you don't need to multiply the percentage and will get better results - fixed






          share|improve this answer

























          • Thank you for your answer! I was working on a solution that was similar to this, but I can see where I went wrong in several places. On line 5 I think it's missing an assignment, right? Also I keep getting "275000" as output with this example, but I haven't figured out why

            – Nick
            May 20 at 13:49












          • Wont the line "percentage = percentage / (100 * 10**decimals);" also get truncated to 0?

            – Nick
            May 20 at 13:55






          • 1





            made several errors in a hurry ... should be fixed now

            – KNK
            May 20 at 14:39











          • Awesome, that seems to work! I'll validate it properly as soon as possible. One more question though. This function will still return a rounded number, right? So would it be better to take out the last line and account for the fact that the last 4 digits are decimals wherever I'm calling the backend from? -or am I doing something wrong?

            – Nick
            May 20 at 14:47






          • 1





            There are no floating point numbers in Solidity (yet), so the number as always rounded at the end, but yes you can return the number as is and divide in the client to get a floating point result

            – KNK
            May 20 at 14:58















          4














          You need to multiply before calculations and divide after that:



          int decimals = 4;
          int totalValue = 275000;
          int percentage = 2;

          totalValue = totalValue * 10**decimals;
          for (uint i = 0; i < 30; i++)
          int AddValue = totalValue * percentage;
          AddValue = AddValue / 100;
          totalValue += AddValue;

          totalValue = totalValue / 10**decimals;


          EDIT: fixed line 5 and the percentage calculation
          EDIT2: Actually you don't need to multiply the percentage and will get better results - fixed






          share|improve this answer

























          • Thank you for your answer! I was working on a solution that was similar to this, but I can see where I went wrong in several places. On line 5 I think it's missing an assignment, right? Also I keep getting "275000" as output with this example, but I haven't figured out why

            – Nick
            May 20 at 13:49












          • Wont the line "percentage = percentage / (100 * 10**decimals);" also get truncated to 0?

            – Nick
            May 20 at 13:55






          • 1





            made several errors in a hurry ... should be fixed now

            – KNK
            May 20 at 14:39











          • Awesome, that seems to work! I'll validate it properly as soon as possible. One more question though. This function will still return a rounded number, right? So would it be better to take out the last line and account for the fact that the last 4 digits are decimals wherever I'm calling the backend from? -or am I doing something wrong?

            – Nick
            May 20 at 14:47






          • 1





            There are no floating point numbers in Solidity (yet), so the number as always rounded at the end, but yes you can return the number as is and divide in the client to get a floating point result

            – KNK
            May 20 at 14:58













          4












          4








          4







          You need to multiply before calculations and divide after that:



          int decimals = 4;
          int totalValue = 275000;
          int percentage = 2;

          totalValue = totalValue * 10**decimals;
          for (uint i = 0; i < 30; i++)
          int AddValue = totalValue * percentage;
          AddValue = AddValue / 100;
          totalValue += AddValue;

          totalValue = totalValue / 10**decimals;


          EDIT: fixed line 5 and the percentage calculation
          EDIT2: Actually you don't need to multiply the percentage and will get better results - fixed






          share|improve this answer















          You need to multiply before calculations and divide after that:



          int decimals = 4;
          int totalValue = 275000;
          int percentage = 2;

          totalValue = totalValue * 10**decimals;
          for (uint i = 0; i < 30; i++)
          int AddValue = totalValue * percentage;
          AddValue = AddValue / 100;
          totalValue += AddValue;

          totalValue = totalValue / 10**decimals;


          EDIT: fixed line 5 and the percentage calculation
          EDIT2: Actually you don't need to multiply the percentage and will get better results - fixed







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited May 20 at 15:14

























          answered May 20 at 13:38









          KNKKNK

          1716




          1716












          • Thank you for your answer! I was working on a solution that was similar to this, but I can see where I went wrong in several places. On line 5 I think it's missing an assignment, right? Also I keep getting "275000" as output with this example, but I haven't figured out why

            – Nick
            May 20 at 13:49












          • Wont the line "percentage = percentage / (100 * 10**decimals);" also get truncated to 0?

            – Nick
            May 20 at 13:55






          • 1





            made several errors in a hurry ... should be fixed now

            – KNK
            May 20 at 14:39











          • Awesome, that seems to work! I'll validate it properly as soon as possible. One more question though. This function will still return a rounded number, right? So would it be better to take out the last line and account for the fact that the last 4 digits are decimals wherever I'm calling the backend from? -or am I doing something wrong?

            – Nick
            May 20 at 14:47






          • 1





            There are no floating point numbers in Solidity (yet), so the number as always rounded at the end, but yes you can return the number as is and divide in the client to get a floating point result

            – KNK
            May 20 at 14:58

















          • Thank you for your answer! I was working on a solution that was similar to this, but I can see where I went wrong in several places. On line 5 I think it's missing an assignment, right? Also I keep getting "275000" as output with this example, but I haven't figured out why

            – Nick
            May 20 at 13:49












          • Wont the line "percentage = percentage / (100 * 10**decimals);" also get truncated to 0?

            – Nick
            May 20 at 13:55






          • 1





            made several errors in a hurry ... should be fixed now

            – KNK
            May 20 at 14:39











          • Awesome, that seems to work! I'll validate it properly as soon as possible. One more question though. This function will still return a rounded number, right? So would it be better to take out the last line and account for the fact that the last 4 digits are decimals wherever I'm calling the backend from? -or am I doing something wrong?

            – Nick
            May 20 at 14:47






          • 1





            There are no floating point numbers in Solidity (yet), so the number as always rounded at the end, but yes you can return the number as is and divide in the client to get a floating point result

            – KNK
            May 20 at 14:58
















          Thank you for your answer! I was working on a solution that was similar to this, but I can see where I went wrong in several places. On line 5 I think it's missing an assignment, right? Also I keep getting "275000" as output with this example, but I haven't figured out why

          – Nick
          May 20 at 13:49






          Thank you for your answer! I was working on a solution that was similar to this, but I can see where I went wrong in several places. On line 5 I think it's missing an assignment, right? Also I keep getting "275000" as output with this example, but I haven't figured out why

          – Nick
          May 20 at 13:49














          Wont the line "percentage = percentage / (100 * 10**decimals);" also get truncated to 0?

          – Nick
          May 20 at 13:55





          Wont the line "percentage = percentage / (100 * 10**decimals);" also get truncated to 0?

          – Nick
          May 20 at 13:55




          1




          1





          made several errors in a hurry ... should be fixed now

          – KNK
          May 20 at 14:39





          made several errors in a hurry ... should be fixed now

          – KNK
          May 20 at 14:39













          Awesome, that seems to work! I'll validate it properly as soon as possible. One more question though. This function will still return a rounded number, right? So would it be better to take out the last line and account for the fact that the last 4 digits are decimals wherever I'm calling the backend from? -or am I doing something wrong?

          – Nick
          May 20 at 14:47





          Awesome, that seems to work! I'll validate it properly as soon as possible. One more question though. This function will still return a rounded number, right? So would it be better to take out the last line and account for the fact that the last 4 digits are decimals wherever I'm calling the backend from? -or am I doing something wrong?

          – Nick
          May 20 at 14:47




          1




          1





          There are no floating point numbers in Solidity (yet), so the number as always rounded at the end, but yes you can return the number as is and divide in the client to get a floating point result

          – KNK
          May 20 at 14:58





          There are no floating point numbers in Solidity (yet), so the number as always rounded at the end, but yes you can return the number as is and divide in the client to get a floating point result

          – KNK
          May 20 at 14:58











          6














          Generally speaking, in order to avoid data-loss (i.e., precision-loss) in an arithmetic computation, try to postpone every division as much as possible, without altering the expression.



          More specifically with regards to your code, it appears that you are trying to compute the result of applying compound interest: 275000 * 1.02 ** 30.



          You can do this very precisely in Solidity, by calculating (off-line) the exact value of 1.02 ** 30, and storing it scaled up to the level of precision that you desire.



          Moreover, you won't even need those 30 iterations in order to achieve all that, so you can optimize your code here for both accuracy and performance.



          For example:



          uint256 INTEREST_N = 181136158410335375505681049921897;
          uint256 INTEREST_D = 10000000000000000000000000000000;
          uint256 totalValue = 275000 * INTEREST_N / INTEREST_D;


          Of course, I'm aware of the fact that you most likely want the 275000 part as an input from the outside rather than a hard-coded value (in which case, you could just as well compute everything outside of the contract).



          But assuming that the number of iterations and the compound interest percentage are both constant (30 and 2% in your case), you can do it using the numerator and denominator described above.



          If either the number of iterations or the compound interest percentage is a variable, then instead of a single pair of numerator and denominator you can use an array of numerators and an array of denominators.



          If both the number of iterations and the compound interest percentage are variables, then instead of a pair of arrays you can use a pair of tables.






          share|improve this answer























          • I appreciate the answer and understand the gist of it, thank you! I'll come back to this solution once my understanding of the issue has improved.

            – Nick
            May 22 at 7:37







          • 1





            @Nick: NP. In your coding example, you could have simply used a constant (or two constants), so I suppose that this example does not represent what you're actually trying to achieve. As explained in my answer, I tend to guess that your intention is for one or more of these constants values (275000, 30 and 2%) to be an input variable. If you provide a description of the actual purpose, then I might be able to guide you through and suggest a scheme which will allow you to realize it while optimizing for both accuracy and performance (i.e., gas cost).

            – goodvibration
            May 22 at 7:42











          • That's awesome! In my case all three of those values are variables, so I figured I might as well send the result of 1.02**30 from the backend/caller. Also, the value of 275000 can contain decimals. At this point I'm not too sure how that will affect the calculation, but added "100000000000000000000000000000000 / (10**decimals);" to make the amount of decimals in the outcome variable.

            – Nick
            May 22 at 8:01












          • To add a more complete description of the variables with examples: the initial value (275000.5115 , max 4 decimals), interest rate (2.2152%, max 4 decimals) and amount of years (30, always a round number). To make it easier I can make sure there's always 4 decimals by padding zeroes.

            – Nick
            May 22 at 8:07












          • @Nick: Sorry, but in that case you can do the full calculation offline and just put the result hard-coded in your contract. There is no need for any code apart from that.

            – goodvibration
            May 22 at 9:37















          6














          Generally speaking, in order to avoid data-loss (i.e., precision-loss) in an arithmetic computation, try to postpone every division as much as possible, without altering the expression.



          More specifically with regards to your code, it appears that you are trying to compute the result of applying compound interest: 275000 * 1.02 ** 30.



          You can do this very precisely in Solidity, by calculating (off-line) the exact value of 1.02 ** 30, and storing it scaled up to the level of precision that you desire.



          Moreover, you won't even need those 30 iterations in order to achieve all that, so you can optimize your code here for both accuracy and performance.



          For example:



          uint256 INTEREST_N = 181136158410335375505681049921897;
          uint256 INTEREST_D = 10000000000000000000000000000000;
          uint256 totalValue = 275000 * INTEREST_N / INTEREST_D;


          Of course, I'm aware of the fact that you most likely want the 275000 part as an input from the outside rather than a hard-coded value (in which case, you could just as well compute everything outside of the contract).



          But assuming that the number of iterations and the compound interest percentage are both constant (30 and 2% in your case), you can do it using the numerator and denominator described above.



          If either the number of iterations or the compound interest percentage is a variable, then instead of a single pair of numerator and denominator you can use an array of numerators and an array of denominators.



          If both the number of iterations and the compound interest percentage are variables, then instead of a pair of arrays you can use a pair of tables.






          share|improve this answer























          • I appreciate the answer and understand the gist of it, thank you! I'll come back to this solution once my understanding of the issue has improved.

            – Nick
            May 22 at 7:37







          • 1





            @Nick: NP. In your coding example, you could have simply used a constant (or two constants), so I suppose that this example does not represent what you're actually trying to achieve. As explained in my answer, I tend to guess that your intention is for one or more of these constants values (275000, 30 and 2%) to be an input variable. If you provide a description of the actual purpose, then I might be able to guide you through and suggest a scheme which will allow you to realize it while optimizing for both accuracy and performance (i.e., gas cost).

            – goodvibration
            May 22 at 7:42











          • That's awesome! In my case all three of those values are variables, so I figured I might as well send the result of 1.02**30 from the backend/caller. Also, the value of 275000 can contain decimals. At this point I'm not too sure how that will affect the calculation, but added "100000000000000000000000000000000 / (10**decimals);" to make the amount of decimals in the outcome variable.

            – Nick
            May 22 at 8:01












          • To add a more complete description of the variables with examples: the initial value (275000.5115 , max 4 decimals), interest rate (2.2152%, max 4 decimals) and amount of years (30, always a round number). To make it easier I can make sure there's always 4 decimals by padding zeroes.

            – Nick
            May 22 at 8:07












          • @Nick: Sorry, but in that case you can do the full calculation offline and just put the result hard-coded in your contract. There is no need for any code apart from that.

            – goodvibration
            May 22 at 9:37













          6












          6








          6







          Generally speaking, in order to avoid data-loss (i.e., precision-loss) in an arithmetic computation, try to postpone every division as much as possible, without altering the expression.



          More specifically with regards to your code, it appears that you are trying to compute the result of applying compound interest: 275000 * 1.02 ** 30.



          You can do this very precisely in Solidity, by calculating (off-line) the exact value of 1.02 ** 30, and storing it scaled up to the level of precision that you desire.



          Moreover, you won't even need those 30 iterations in order to achieve all that, so you can optimize your code here for both accuracy and performance.



          For example:



          uint256 INTEREST_N = 181136158410335375505681049921897;
          uint256 INTEREST_D = 10000000000000000000000000000000;
          uint256 totalValue = 275000 * INTEREST_N / INTEREST_D;


          Of course, I'm aware of the fact that you most likely want the 275000 part as an input from the outside rather than a hard-coded value (in which case, you could just as well compute everything outside of the contract).



          But assuming that the number of iterations and the compound interest percentage are both constant (30 and 2% in your case), you can do it using the numerator and denominator described above.



          If either the number of iterations or the compound interest percentage is a variable, then instead of a single pair of numerator and denominator you can use an array of numerators and an array of denominators.



          If both the number of iterations and the compound interest percentage are variables, then instead of a pair of arrays you can use a pair of tables.






          share|improve this answer













          Generally speaking, in order to avoid data-loss (i.e., precision-loss) in an arithmetic computation, try to postpone every division as much as possible, without altering the expression.



          More specifically with regards to your code, it appears that you are trying to compute the result of applying compound interest: 275000 * 1.02 ** 30.



          You can do this very precisely in Solidity, by calculating (off-line) the exact value of 1.02 ** 30, and storing it scaled up to the level of precision that you desire.



          Moreover, you won't even need those 30 iterations in order to achieve all that, so you can optimize your code here for both accuracy and performance.



          For example:



          uint256 INTEREST_N = 181136158410335375505681049921897;
          uint256 INTEREST_D = 10000000000000000000000000000000;
          uint256 totalValue = 275000 * INTEREST_N / INTEREST_D;


          Of course, I'm aware of the fact that you most likely want the 275000 part as an input from the outside rather than a hard-coded value (in which case, you could just as well compute everything outside of the contract).



          But assuming that the number of iterations and the compound interest percentage are both constant (30 and 2% in your case), you can do it using the numerator and denominator described above.



          If either the number of iterations or the compound interest percentage is a variable, then instead of a single pair of numerator and denominator you can use an array of numerators and an array of denominators.



          If both the number of iterations and the compound interest percentage are variables, then instead of a pair of arrays you can use a pair of tables.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered May 20 at 15:25









          goodvibrationgoodvibration

          5,11911127




          5,11911127












          • I appreciate the answer and understand the gist of it, thank you! I'll come back to this solution once my understanding of the issue has improved.

            – Nick
            May 22 at 7:37







          • 1





            @Nick: NP. In your coding example, you could have simply used a constant (or two constants), so I suppose that this example does not represent what you're actually trying to achieve. As explained in my answer, I tend to guess that your intention is for one or more of these constants values (275000, 30 and 2%) to be an input variable. If you provide a description of the actual purpose, then I might be able to guide you through and suggest a scheme which will allow you to realize it while optimizing for both accuracy and performance (i.e., gas cost).

            – goodvibration
            May 22 at 7:42











          • That's awesome! In my case all three of those values are variables, so I figured I might as well send the result of 1.02**30 from the backend/caller. Also, the value of 275000 can contain decimals. At this point I'm not too sure how that will affect the calculation, but added "100000000000000000000000000000000 / (10**decimals);" to make the amount of decimals in the outcome variable.

            – Nick
            May 22 at 8:01












          • To add a more complete description of the variables with examples: the initial value (275000.5115 , max 4 decimals), interest rate (2.2152%, max 4 decimals) and amount of years (30, always a round number). To make it easier I can make sure there's always 4 decimals by padding zeroes.

            – Nick
            May 22 at 8:07












          • @Nick: Sorry, but in that case you can do the full calculation offline and just put the result hard-coded in your contract. There is no need for any code apart from that.

            – goodvibration
            May 22 at 9:37

















          • I appreciate the answer and understand the gist of it, thank you! I'll come back to this solution once my understanding of the issue has improved.

            – Nick
            May 22 at 7:37







          • 1





            @Nick: NP. In your coding example, you could have simply used a constant (or two constants), so I suppose that this example does not represent what you're actually trying to achieve. As explained in my answer, I tend to guess that your intention is for one or more of these constants values (275000, 30 and 2%) to be an input variable. If you provide a description of the actual purpose, then I might be able to guide you through and suggest a scheme which will allow you to realize it while optimizing for both accuracy and performance (i.e., gas cost).

            – goodvibration
            May 22 at 7:42











          • That's awesome! In my case all three of those values are variables, so I figured I might as well send the result of 1.02**30 from the backend/caller. Also, the value of 275000 can contain decimals. At this point I'm not too sure how that will affect the calculation, but added "100000000000000000000000000000000 / (10**decimals);" to make the amount of decimals in the outcome variable.

            – Nick
            May 22 at 8:01












          • To add a more complete description of the variables with examples: the initial value (275000.5115 , max 4 decimals), interest rate (2.2152%, max 4 decimals) and amount of years (30, always a round number). To make it easier I can make sure there's always 4 decimals by padding zeroes.

            – Nick
            May 22 at 8:07












          • @Nick: Sorry, but in that case you can do the full calculation offline and just put the result hard-coded in your contract. There is no need for any code apart from that.

            – goodvibration
            May 22 at 9:37
















          I appreciate the answer and understand the gist of it, thank you! I'll come back to this solution once my understanding of the issue has improved.

          – Nick
          May 22 at 7:37






          I appreciate the answer and understand the gist of it, thank you! I'll come back to this solution once my understanding of the issue has improved.

          – Nick
          May 22 at 7:37





          1




          1





          @Nick: NP. In your coding example, you could have simply used a constant (or two constants), so I suppose that this example does not represent what you're actually trying to achieve. As explained in my answer, I tend to guess that your intention is for one or more of these constants values (275000, 30 and 2%) to be an input variable. If you provide a description of the actual purpose, then I might be able to guide you through and suggest a scheme which will allow you to realize it while optimizing for both accuracy and performance (i.e., gas cost).

          – goodvibration
          May 22 at 7:42





          @Nick: NP. In your coding example, you could have simply used a constant (or two constants), so I suppose that this example does not represent what you're actually trying to achieve. As explained in my answer, I tend to guess that your intention is for one or more of these constants values (275000, 30 and 2%) to be an input variable. If you provide a description of the actual purpose, then I might be able to guide you through and suggest a scheme which will allow you to realize it while optimizing for both accuracy and performance (i.e., gas cost).

          – goodvibration
          May 22 at 7:42













          That's awesome! In my case all three of those values are variables, so I figured I might as well send the result of 1.02**30 from the backend/caller. Also, the value of 275000 can contain decimals. At this point I'm not too sure how that will affect the calculation, but added "100000000000000000000000000000000 / (10**decimals);" to make the amount of decimals in the outcome variable.

          – Nick
          May 22 at 8:01






          That's awesome! In my case all three of those values are variables, so I figured I might as well send the result of 1.02**30 from the backend/caller. Also, the value of 275000 can contain decimals. At this point I'm not too sure how that will affect the calculation, but added "100000000000000000000000000000000 / (10**decimals);" to make the amount of decimals in the outcome variable.

          – Nick
          May 22 at 8:01














          To add a more complete description of the variables with examples: the initial value (275000.5115 , max 4 decimals), interest rate (2.2152%, max 4 decimals) and amount of years (30, always a round number). To make it easier I can make sure there's always 4 decimals by padding zeroes.

          – Nick
          May 22 at 8:07






          To add a more complete description of the variables with examples: the initial value (275000.5115 , max 4 decimals), interest rate (2.2152%, max 4 decimals) and amount of years (30, always a round number). To make it easier I can make sure there's always 4 decimals by padding zeroes.

          – Nick
          May 22 at 8:07














          @Nick: Sorry, but in that case you can do the full calculation offline and just put the result hard-coded in your contract. There is no need for any code apart from that.

          – goodvibration
          May 22 at 9:37





          @Nick: Sorry, but in that case you can do the full calculation offline and just put the result hard-coded in your contract. There is no need for any code apart from that.

          – goodvibration
          May 22 at 9:37











          2














          The reason you are getting the value 498108 is because Solidity truncates divided values.



          This means that if you divide 3/2, the result will be 1, not 1.5. Similarly, if you divide 11/3, the result will be 3, not 3.666.



          With this in mind, the reason you are getting that final result is because a few of the loop results are being truncated.






          share|improve this answer

























          • So you're saying that it's not possible in any way? I'm aware of what's happening (actually I thought it was rounding it down/up, but you're saying it's truncating. Thanks for letting me know!), but I don't know how else to approach this to get the result I want.

            – Nick
            May 20 at 13:02
















          2














          The reason you are getting the value 498108 is because Solidity truncates divided values.



          This means that if you divide 3/2, the result will be 1, not 1.5. Similarly, if you divide 11/3, the result will be 3, not 3.666.



          With this in mind, the reason you are getting that final result is because a few of the loop results are being truncated.






          share|improve this answer

























          • So you're saying that it's not possible in any way? I'm aware of what's happening (actually I thought it was rounding it down/up, but you're saying it's truncating. Thanks for letting me know!), but I don't know how else to approach this to get the result I want.

            – Nick
            May 20 at 13:02














          2












          2








          2







          The reason you are getting the value 498108 is because Solidity truncates divided values.



          This means that if you divide 3/2, the result will be 1, not 1.5. Similarly, if you divide 11/3, the result will be 3, not 3.666.



          With this in mind, the reason you are getting that final result is because a few of the loop results are being truncated.






          share|improve this answer















          The reason you are getting the value 498108 is because Solidity truncates divided values.



          This means that if you divide 3/2, the result will be 1, not 1.5. Similarly, if you divide 11/3, the result will be 3, not 3.666.



          With this in mind, the reason you are getting that final result is because a few of the loop results are being truncated.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited May 20 at 18:46

























          answered May 20 at 11:48









          shaneshane

          2,6224932




          2,6224932












          • So you're saying that it's not possible in any way? I'm aware of what's happening (actually I thought it was rounding it down/up, but you're saying it's truncating. Thanks for letting me know!), but I don't know how else to approach this to get the result I want.

            – Nick
            May 20 at 13:02


















          • So you're saying that it's not possible in any way? I'm aware of what's happening (actually I thought it was rounding it down/up, but you're saying it's truncating. Thanks for letting me know!), but I don't know how else to approach this to get the result I want.

            – Nick
            May 20 at 13:02

















          So you're saying that it's not possible in any way? I'm aware of what's happening (actually I thought it was rounding it down/up, but you're saying it's truncating. Thanks for letting me know!), but I don't know how else to approach this to get the result I want.

          – Nick
          May 20 at 13:02






          So you're saying that it's not possible in any way? I'm aware of what's happening (actually I thought it was rounding it down/up, but you're saying it's truncating. Thanks for letting me know!), but I don't know how else to approach this to get the result I want.

          – Nick
          May 20 at 13:02


















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Ethereum Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fethereum.stackexchange.com%2fquestions%2f70898%2fhandling-decimals-in-somewhat-complex-math%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          How to write a 12-bar blues melodyI-IV-V blues progressionHow to play the bridges in a standard blues progressionHow does Gdim7 fit in C# minor?question on a certain chord progressionMusicology of Melody12 bar blues, spread rhythm: alternative to 6th chord to avoid finger stretchChord progressions/ Root key/ MelodiesHow to put chords (POP-EDM) under a given lead vocal melody (starting from a good knowledge in music theory)Are there “rules” for improvising with the minor pentatonic scale over 12-bar shuffle?Confusion about blues scale and chords

          What if the end-user didn't have the required library?What is setup.py?What is a clean, pythonic way to have multiple constructors in Python?What does Ruby have that Python doesn't, and vice versa?What is the reason for having '//' in Python?How do I create a namespace package in Python?How to package shared objects that python modules depend on?setuptools vs. distutils: why is distutils still a thing?Navigation in Windows 10 vs code not going to virtualenv library when the same library is installed at user levelPython create package for local usePackaging a project that uses multiple python versionsWhy is permission denied on pip install except for when “--user” is included at end of command?

          Why did Thanos need his ship to help him in the battle scene?Which actor plays Thanos in the Avengers mid-credits scene?Are there economic implications portrayed in comics where the buildings and cities are ruined almost daily?Old X-Men comic where team travels to alien world with a ring-like sun that needs recharging?Why does Ego need help sleeping?Is there an objective answer to who “the strongest Avenger” is?How did Banner get unstuck?Why did Thanos get hit?How did Thanos (or anyone) know the Infinity Stones would give him this power?Did Thanos leave Eitri alive for his after-sales service?In Avengers 1, why does Thanos need Loki?