Fractional count through integers

I get an integer, which is the sum in dollars in fractional denominations. I need an algorithm that can add these numbers indiscriminately and convert them to double or decimal numbers.

For example, I get the integer 50155, which means 50 and 15.5 / 32 dollars. Then I get 10210, which is 10 and 21/32 dollars. So, 50 15,5 / 32 + 10 21/32 = 61 4,5 / 32, thus:

50 155 + 10 210 = 61045

Again, I want to avoid this:

int a = 50155; int b = a / 1000; float c = a % 1000; float d = b; d += c / 320f; // d = 50.484375 

I would prefer this:

 int a = 50155; int b = 10210; int c = MyClass.Add(ab); // c = 61045 ... public int Add(int a, int b) { // ????? } 

Thanks in advance for your help!

+6
c # algorithm
source share
7 answers

Well, I don’t think you need to use floating point ...

 public static int Add(int a, int b) { int firstWhole = a / 1000; int secondWhole = b / 1000; int firstFraction = a % 1000; int secondFraction = b % 1000; int totalFraction = firstFraction + secondFraction; int totalWhole = firstWhole + secondWhole + (totalFraction / 320); return totalWhole * 1000 + (totalFraction % 320); } 

Alternatively, you may need to create a custom structure that can convert to and from your integer format, and overloads the + operator. This would allow you to write more readable code that would not accidentally cause other integers to be processed as this odd format.

EDIT: If you are forced to adhere to the “one whole” format, but you can tweak it a bit, you might want to use 512 instead of 1000. So you can use a simple mask and shift:

 public static int Add(int a, int b) { int firstWhole = a >> 9; int secondWhole = b >> 9; int firstFraction = a & 0x1ff int secondFraction = b & 0x1ff; int totalFraction = firstFraction + secondFraction; int totalWhole = firstWhole + secondWhole + (totalFraction / 320); return (totalWhole << 9) + (totalFraction % 320); } 

There is still a problem with 320, but it is at least somewhat better.

+4
source share

A line break in the part representing whole dollars and that part which is the fraction of dollars. For the latter, instead of considering it as 10.5 thirty seconds of a dollar, it is probably easier to consider it as 105 three hundred and twenty dollars (i.e., multiplying by ten by the numerator is always an integer).

From there, the math is pretty simple (if a little tedious to write): add fractions. If it exceeds the entire dollar, carry the dollar (and subtract 320 from the share). Then add all the dollars. Subtraction is similar - although in this case you need to borrow instead of wearing it.

+3
source share

Edit :
This answer assumes that one "stays" from float arithmetic. Surprisingly, the OP indicated that its floating point logic (not shown for property reasons) was twice as fast as the integer solution modulo below! Shows that FPUs are not so bad ...

Definitely stay away from floats (for this particular problem). Integer arithmetic is more efficient and does not lead to rounding errors.

Something like the following should do the trick
Note. As indicated, it is assumed that A and B are positive.

 int AddMyOddlyEncodedDollars (int A, int B) { int sum; sum = A + B if (sum % 1000 < 320); return sum else return sum + 1000 - 320; } 

Edit : about the efficiency of the modulo operator in C
I am very dependent on the compiler ... Since the value of modulo is known at compile time, I would expect most modern compilers to switch to "multiply [by mutual] and shift", and this is fast.
This concern about performance (with this fairly invented format) is a challenge to premature optimization, but again, I saw that the software in the financial industry is highly optimized (politely), and it is justified.

+3
source share

As a learning point, this representation is called a " fixed point ". There are a number of implementations that you can look at. I would highly recommend that you do not use int as your top-level data type, but instead create a type of Fixed that encapsulates operations. It will keep your error counter when you mistakenly add a simple int to a fixed point number without decreasing it first, or decrease the number and forget it.

+2
source share

Looks like a weird encoding.

In any case, if the format is in the 10-base Nxxx, where N is an integer representing whole dollars, and xxx is interpreted as

(xxx / 320)

and you want to add them together, the only thing you need to handle is porting when xxx exceeds 320:

 int a = ..., b = ...; // dollar amounts int c = (a + b); // add together // Calculate carry int carry = (c % 1000) / 320; // integer division c += carry * 1000; c -= carry * 320; // done 

Note: this works because if a and b are encoded correctly, the fractional parts are combined up to a maximum of 638 and, therefore, there is no “overflow” of the entire part of the dollar.

+1
source share

If you insist on working in ints, you cannot solve your problem indiscriminately - because your data is not integer. I give evidence (so far) of 3 answers that all analyze your ints in their components before doing arithmetic.

An alternative would be to use rational numbers with 2 (integer) components, one for the whole part and one for the 320's in the fractional part. Then do the appropriate rational arithmetic. As always, carefully choose your data representations, and your algorithms become much easier to implement.

I can’t say that I think this alternative is especially better on any axis of comparison, but it can satisfy your desire not to analyze.

0
source share

BEWARE : This post is wrong, wrong, wrong . I will remove it as soon as I stop feeling like a fool to try it.

Here is my move: you can trade space for time .

Construct a mapping for the first 10 bits in a tuple: the number of dollars, the number of pieces is 32. Then use bit-manipulation by an integer:

  • ignore bits 11 and above, apply the card.
  • shift the integer 10 times, add small change dollars from the display above.
  • Now you have a dollar, and the number of pieces in the amount of
  • add both
    • move overflow to dollar amount

Then, to convert back to “canonical” notation, you need a reverse search map for your details and “borrow” dollars to fill in the bits. Shift dollars 10 times and add slices 32.

EDIT: I have to delete this, but I'm very ashamed. Of course, he cannot work. I'm so stupid: (

The reason is that a shift of 10 to the right is the same as dividing by 1024 - it is not as if some of the least significant bits had a dollar amount and a certain amount of 32. Decimal and binary notations are simply not split. This is why we use hexadecimal notation (grouping by 4 bits). Bummer.

0
source share

All Articles