LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-18-2015, 09:07 PM   #1
EldonCool
Member
 
Registered: Dec 2010
Location: Nevada
Distribution: Slackware
Posts: 258

Rep: Reputation: 3
Computers can't add or subtract.


I have started keeping track of my stock accounts with my computer.

I wrote a simple C program that will read a file of numbers like this, to keep track of cash balance:

316918.80
52.10
2.46
-1803.26
-901.93
-41493.28
-18932.08
3997.26
qqqq

1st line is starting balance
next lines are transactions, additions and subtractions
from buys, sells, dividends, interest etc.

Schwab says the new balance after that starting above
and with those tranactions are:

$257,840.11

My C program reads a file like that and keeps
a running total until it reaches a line with
the letter q in it, then it stops and gives the
new balance. My program says new balance is:

enter numbers to add, Q to quit
line 1 num 316918.812500, tot 316918.812500
line 2 num 52.099998, tot 316970.906250
line 3 num 2.460000, tot 316973.375000
line 4 num -1803.260010, tot 315170.125000
line 5 num -901.929993, tot 314268.187500
line 6 num -41493.281250, tot 272774.906250
line 7 num -18932.000000, tot 253842.906250
line 8 num 3997.260010, tot 257840.171875

So my C program said the balance was

$257,840.17

6 cents more.

Just for fun, I moved the first line of the
file, to the last line, and then ran the
program, results:

enter numbers to add, Q to quit
line 1 num 52.099998, tot 52.099998
line 2 num 2.460000, tot 54.559998
line 3 num -1803.260010, tot -1748.699951
line 4 num -901.929993, tot -2650.629883
line 5 num -41493.281250, tot -44143.910156
line 6 num -18932.000000, tot -63075.910156
line 7 num 3997.260010, tot -59078.648438
line 8 num 316918.812500, tot 257840.156250

Now it says total is:

257,840.16

One cent different just by changing the order
of the numbers added.

Now remove the decimal points and add them
total up as pennies instead of dollars:

enter numbers to add, Q to quit
line 1 num 5210.000000, tot 5210.000000
line 2 num 246.000000, tot 5456.000000
line 3 num -180326.000000, tot -174870.000000
line 4 num -90193.000000, tot -265063.000000
line 5 num -4149328.000000, tot -4414391.000000
line 6 num -1893208.000000, tot -6307599.000000
line 7 num 399726.000000, tot -5907873.000000
line 8 num 31691880.000000, tot 25784008.000000

Now total comes to:

257,840.08


I lost 8 cents just by changing to pennies
instead of dollars.

Next I modified my run_tot.c to read the
amount in as a long integer, then removed
the decimal point from the file of numbers
so they are this:

31691880
5210
246
-180326
-90193
-4149328
-1893208
399726
qqqq

Now it did this:
enter numbers to add, Q to quit
line 1 num 5210, tot 5210
line 2 num 246, tot 5456
line 3 num -180326, tot -174870
line 4 num -90193, tot -265063
line 5 num -4149328, tot -4414391
line 6 num -1893208, tot -6307599
line 7 num 399726, tot -5907873
line 8 num 31691880, tot 25784007

final answer 25784007 pennies,
or $257,840.07

This one looks to be correct, so you
have to do integer math to get the
right answer, last two digits = 07.

floating point gave me these last two digits
done various ways: 11, 17, 16, 08

This is more error than I would have guessed
using floating point.
 
Old 03-18-2015, 11:52 PM   #2
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: Rocky Linux
Posts: 4,776

Rep: Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212
Now you know why accounting programs never use floating point arithmetic. With single precision, you run out of precision to represent an increment of .01 at all when the value reaches 262144 (adding .01 no longer changes the variable). Even with double precision, most decimal fractions simply cannot be represented exactly.
 
1 members found this post helpful.
Old 03-19-2015, 12:15 AM   #3
veerain
Senior Member
 
Registered: Mar 2005
Location: Earth bound to Helios
Distribution: Custom
Posts: 2,524

Rep: Reputation: 319Reputation: 319Reputation: 319Reputation: 319
Yes. C language single and double precison arithmetic is not good for financial softwares. Instead you should use decimal arithmetics library.

Here are link1 and link2 which have important points and links.
 
Old 03-19-2015, 01:30 AM   #4
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,856
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
(It's not exactly the language, it's the CPU (and the IEEE standard it implements). Even 0.2(=1/5) cannot be precisely represented. We have to live with it.)
 
Old 03-19-2015, 09:13 AM   #5
genss
Member
 
Registered: Nov 2013
Posts: 741

Rep: Reputation: Disabled
for money, fixed-point number representations are used
afaik
 
Old 03-19-2015, 09:22 AM   #6
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 11,219

Rep: Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309
If you don't need factions of cents, then just use integer numbers of cents.
 
Old 03-19-2015, 10:25 AM   #7
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
Single precision floats are only good to ~7 significant digits. You went past that, which is why you got roundoff error. Double precision floats are good to ~15 significant digits, which should get you into the trillions of dollars without issue.
 
1 members found this post helpful.
Old 03-19-2015, 11:37 AM   #8
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 11,219

Rep: Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309Reputation: 5309
Here's a good thread about floating-point rounding errors:

http://www.linuxquestions.org/questi...nd-4175494658/

Last edited by dugan; 03-24-2015 at 04:18 PM.
 
Old 03-19-2015, 12:02 PM   #9
metaschima
Senior Member
 
Registered: Dec 2013
Distribution: Slackware
Posts: 1,982

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
Use gnumeric, don't write your own unless you use a library that handles numbers properly.
 
Old 03-20-2015, 09:24 AM   #10
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
I'd switch to integers or longs and convert back when calculations are complete.

Be aware of the sizeof variables in your machine. It's always good to run a test program which does:
Code:
printf("Size of short is: %d\n", sizeof(short));
printf("Size of int is: %d\n", sizeof(int));
// And so on - but I don't check the size of a float or double
// Just char, short, int, and long usually
 
Old 03-22-2015, 11:03 PM   #11
EldonCool
Member
 
Registered: Dec 2010
Location: Nevada
Distribution: Slackware
Posts: 258

Original Poster
Rep: Reputation: 3
I rewrote my program and read the numbers into a double float
to begin with, then added that to double total. Doing that
the answer comes out right now.

Reading each number into a double was a bit of a puzzle for
awhile, but finally got it to work using strtod(). Also
displaying required a change in my printf statement in the
format in order to actually print the amount correct.

I did a search on gnumeric to find out what it is, looks
like a good deal if you want to use spread sheets.
 
1 members found this post helpful.
Old 03-23-2015, 09:12 AM   #12
genss
Member
 
Registered: Nov 2013
Posts: 741

Rep: Reputation: Disabled
as long as you don't use it for business, that's fine
 
Old 03-23-2015, 07:46 PM   #13
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,647
Blog Entries: 4

Rep: Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933
Here's the problem, in a nutshell . . .

If you define a variable, or any value, as "float(ing point)," the computer represents that number in the same way that a scientific calculator does: as a so-called mantissa and an exponent.

This representation is very useful ... in certain settings ... because it allows "very(!) large numbers" to be represented and to be meaningfully processed. For example, a number such as 8.12345 E+16 represents "a very large number" with 16(!) zeroes to the right of the decimal point. ("E+16" is the exponent; the other part is the mantissa.)

Very nice for engineering.

Utterly useless(!) for accounting.

Why? Because, the mantissa/exponent is still there, even if you don't "see" it. 1.234000 E+01 would probably be shown to you as 12.34, but, in the bowels of the machine, it's still that floating-point number.

Accountants don't like that. Accountants want things to add up "to the penny.™" Which actually means that they accept require(!) a form of numerical inaccuracy that "the floating-point format" is intended to prevent!

... and ... "nevermind. The accountants, by definition, are always right."

Therefore, some different form of representation must be used for "dollars-and-cents." This representation must be one that conforms to the accountant's expectations requirements.

Probably the most-common representation that is used, today, is a "scaled integer." $12.34 would be represented by (most commonly ...) the integer value "12,340,000." This provides four digits to the right of the decimal point. Or, it might be represented by "123,400," providing two.

Don't ask. The accountants are always right.
 
1 members found this post helpful.
Old 03-23-2015, 07:50 PM   #14
metaschima
Senior Member
 
Registered: Dec 2013
Distribution: Slackware
Posts: 1,982

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
Using scaled integers is a good solution, you don't actually need floating point numbers here.
 
Old 03-23-2015, 09:12 PM   #15
EldonCool
Member
 
Registered: Dec 2010
Location: Nevada
Distribution: Slackware
Posts: 258

Original Poster
Rep: Reputation: 3
Interesting, the different ways. One thing that I
find interesting is that Schwab apparently is not
using the accounting approved ways, talked about
above, because their answer is off slightly from
what was correct. They must be using floating point.

I really don't care if my answer is off a few cents
for this application I have been working on. I really
just want a way to get a correct answer to a series
of trades made. You would think that would be straight
forward, but it is not.

The government keeps putting in idiotic rules about
calculating gains and losses for tax purposes. The
latest one to give headaches is their disallowed
losses.

If you buy a stock for $100 and then sell it for $50,
You have a $50 loss, but if you buy the stock back
within 30 days, then they "disallow" the loss. Also
if you buy a call option on it within 30 days, they
disallow the loss, also if you sell a put option on
it within 30 days they disallow it.

Actually the loss is allowed but you have to go through
a bunch of BS in order to get it. So when you buy back
the stock within 30 days, they say it only adjusts your
cost basis, and they don't allow the loss. Here is
an example:

You buy for 100, later sell for 75,
then buy for 76, then sell for 80.

The first line there they disallow the 25 loss because
you bought it back on the second line. So you don't
have a loss, you now have an adjusted cost basis.

You can't take your loss until you are completely
out of the stock for more than 30 days, so
eventually:

costs: 100 + 76 = 176
sales: 75 + 80 = 155

So finally you have a 21 dollar loss.
But the broker has to keep track of all this
as cost basis adjustments,

The way they do it with adjustments though:
Cost 100 originally
sell for 75 and buy for 76, here is a dollar loss, so you add
1 dollar to original cost basis, so now
your cost basis is 101, not 100.

You sell for 80, and now 101 - 80 = 21 loss.
Same figure if you just used the straight forward
without all the adjustments. Democrats have done
this to try an extract the last dollar of income
tax, so you defer your loss until next year, when
the democrats will then get less tax from you.

Anyway now with all this adjusted allowance, you
cannot figure out whether you made money or not
just looking at your statement, and they report
their figures to the IRS. Fact is though,
they consistently are showing people making more
money than they do.

So how do you check their figures? The easiest
way is to just take all the buy and sell transactions
and add them up. If your bottom line is the same
as their bottom line, then they got it right.
If, they don't get it right, and I am pretty sure
they often get it wrong, then you are going to
be hosed when you pay your taxes.

So I now keep a running total of all transactions
in all accounts, and I can instantly get a bottom
line on any one stock within seconds.

I keep the records in a dbase file and I can sort
on date, and stock symbol grouping any one stock
with all its options together. I can cut and
paste the column of figures for all the buys and
sells and have my program that totals them by
reading a file where I paste the batch of figures
with the buy and sell.

It also allows me to check their math for keeping
my cash balance at all times.

I just went through taxes the last few weeks, and
trying to get an accurate gain/loss record with
broker statements is like pulling teeth, but with
my running list of transactions, I can spit them
out in seconds, with no errors.

Next year is going to be much easier to figure than
this year. because I can instantly see errors in
the reporting.

It is amazing but I cannot even get things to balance
using complete lists of all transactions provided by
the brokers. I use several brokers and they all use
different formats, and somehow the figures I come
up with using their own files does not jive with
what they come up with.

Anyway, now using the double float, my answers are
very good.

They have made this reporting so complex, the programmers
for brokers must be going nuts, and I suspect we have
a lot of errors in programming giving the old garbage
in, garbage out problem.

Last edited by EldonCool; 03-23-2015 at 09:36 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Add users to Multiple Computers at Once? DiskChris Linux - General 3 12-16-2012 09:39 AM
How to subtract days HyperTrey Programming 15 06-06-2008 03:45 AM
How to subtract two date in Perl? abdul_zu Programming 8 12-08-2007 09:59 AM
Security risk for Windows workgroup computers if I add a Linux webserver? rreiss Linux - Security 1 03-17-2006 12:51 PM
using bc to subtract hexdemical schurt Linux - Software 1 01-07-2005 01:18 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:23 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration