A good maths parser

Programming, for all ages and all languages.
User avatar
Thomas
Member
Member
Posts: 281
Joined: Thu Jun 04, 2009 11:12 pm

Re: A good maths parser

Post by Thomas »

Hi ,
A simple solution came to my mind :mrgreen: . It may be flawed however . We know that 0.9999999999999999.... ( followed by infinite number of 9) is 1 itself .

Proof .

0.9999999999... = 0.9 * 10^0 + 0.9 * 10 ^ -1 + 0.9 * 10 ^ -2 ...
ie it represents a Geometric Progression with 10 ^ -1 as common factor . Sum of a Infinite geometric progression is a / (1 -r) where a = first term , r = common factor where r < 1 , if r >= 1 then the series is divergent and the sum is infinite .

Sum = 0.9 / ( 1 - 10 ^ -1 ) = 0.9 / ( 1 - 0.1) = 1 ( hence proved ) . Therefore when there are good number of 9s after the decimal point we can aproximate it as a whole number .

So ( 1 / 3) * 3 = 0.9999999999... , would approximated as a 1 ( Say We consider only 5 nines past the decimal )
similary ( 2 / 3 ) * 3 = 0.666... * 3 = 1.999.....8
= 2 ( Say we consider only 5 nines past the decimal )


--Thomas
User avatar
Thomas
Member
Member
Posts: 281
Joined: Thu Jun 04, 2009 11:12 pm

Re: A good maths parser

Post by Thomas »

Hi ,

You guys are incorrect it seems , ouput is 2.00 , if a = 3.0 and b = 2.0 and 3.00 if a = 3.0 and b = 1.0

Code: Select all

#include "stdafx.h"
#include <stdio.h> 
#include <conio.h> 
int _tmain(int argc, _TCHAR* argv[])
{
  float a = 3.0f ; 
  float b = 4.0f ; 
  scanf("%f %f", &a , & b) ; 
  float x =  b / a ;  
  float y =  x * 3.0f ; 
  printf("%f" , y ) ; 
  getch() ; 
}



--Thomas
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: A good maths parser

Post by Owen »

MessiahAndrw wrote:I think you're getting away from the point Brendan and I made. No matter how precise you're wanting to store a number, if you calculate 1 / 3 * 6 after each operation then you'll get 1.99999999999999999999999999999 unless in memory you store that number is equal to "1 / 3" then when you multiple by 6 it'll cancel out the "/ 3" and turn it into "* 2", in which case when you output the number (when the actual calculation occurs) it will return 2.

You can never predict where such accuracy may be needed over the speed, but I'm sure there are areas that would benefit from it that could run for years on end without the data being interfered with by rounding errors.
Yes, but the simple fact is that the method which has been used for years (and nobody has complained about it) is to do the maths to the precision afforded by the involved data types, and include a way to specify what to use. In other words, the C way, in which "float f = 1/3" will actually produce 0, and you probably want "float f = 1.f / 3.f".

The important factor here is that maths should behave identically whether evaluated at compile time or runtime. If your language develops a very clever optimizer, and you use a complex number format for intermediaries, then you may end up in a situation where no optimizations and optimizations behave differently in hard to understand ways, which is never desirable.
User avatar
AndrewAPrice
Member
Member
Posts: 2299
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: A good maths parser

Post by AndrewAPrice »

Owen wrote:Yes, but the simple fact is that the method which has been used for years (and nobody has complained about it) is to do the maths to the precision afforded by the involved data types, and include a way to specify what to use. In other words, the C way, in which "float f = 1/3" will actually produce 0, and you probably want "float f = 1.f / 3.f".
I'm talking about representing math equations at a higher level, which is nothing to do with decimal precision of the numbers stored.
My OS is Perception.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: A good maths parser

Post by Owen »

MessiahAndrw wrote:
Owen wrote:Yes, but the simple fact is that the method which has been used for years (and nobody has complained about it) is to do the maths to the precision afforded by the involved data types, and include a way to specify what to use. In other words, the C way, in which "float f = 1/3" will actually produce 0, and you probably want "float f = 1.f / 3.f".
I'm talking about representing math equations at a higher level, which is nothing to do with decimal precision of the numbers stored.
Which is probably not what you want when implementing a compiler or assembler...
User avatar
AndrewAPrice
Member
Member
Posts: 2299
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: A good maths parser

Post by AndrewAPrice »

Owen wrote:
MessiahAndrw wrote:I'm talking about representing math equations at a higher level, which is nothing to do with decimal precision of the numbers stored.
Which is probably not what you want when implementing a compiler or assembler...
Unless the compiler happens to be for a functional language such as a Haskel variant.
My OS is Perception.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: A good maths parser

Post by Brendan »

Hi,
Thomas wrote:You guys are incorrect it seems , ouput is 2.00 , if a = 3.0 and b = 2.0 and 3.00 if a = 3.0 and b = 1.0
That's because the rounding errors cancel each other out. For an example, using three digits:

2/3 = 667*10^(-3)
667*10^(-3) * 3 = 200*10^(-2) = 2

Now try "((4/3)-1)*3" from my post:

Code: Select all

#include <stdio.h>

int main(int argc, char *argv[]) {
	float a = 3.0f;
	float b = 4.0f;
	float c = 1.0f;
	float x;

	x = (b/a - c) * a;
	printf("%#.30f\n", x);
}

Code: Select all

1.000000119209289550781250000000
And now with "double":

Code: Select all

#include <stdio.h>

int main(int argc, char *argv[]) {
	double a = 3.0f;
	double b = 4.0f;
	double c = 1.0f;
	double x;

	x = (b/a - c) * a;
	printf("%#.30f\n", x);
}

Code: Select all

0.999999999999999777955395074969
Now, let's do it with an 8-bit relational numbers (4-bit numerator and 4-bit divisor):

Code: Select all

a = {0011b / 0001b};
b = {0100b / 0001b};
c = {0001b / 0001b};
x = (b/a - c) * a
  = ( {0100b / 0001b} / {0011b / 0001b} - {0001b / 0001b} ) * {0011b / 0001b}; // Replace variables
  = ( {0100b / 0001b} * {0001b / 0011b} - {0001b / 0001b} ) * {0011b / 0001b}; // Multiply by reciprocal rather than divide
  = ( {1100b / 0011b} * {0001b / 0011b} - {0001b / 0001b} ) * {0011b / 0001b}; // Get divisors the same
  = ( {1100b / 1001b} - {0001b / 0001b} ) * {0011b / 0001b};                   // Do first multiplication
  = ( {0100b / 0011b} - {0001b / 0001b} ) * {0011b / 0001b};                   // Remove highest common denominator (3)
  = ( {0100b / 0011b} - {0011b / 0011b} ) * {0011b / 0001b};                   // Get divisors the same
  = {0001b / 0011b} * {0011b / 0001b};                                         // Do subtraction
  = {0001b / 0011b} * {0011b / 0001b};                                         // Remove highest common denominator (1)
  = {0001b / 0011b} * {1001b / 0011b};                                         // Get divisors the same
  = {1001b / 1001b};                                                           // Do second multiplication
  = {0001b / 0001b};                                                           // Remove highest common denominator (9)
  = 1
Who wants to know what 0.1 looks like in binary? Here it is (it's recursive):

0.000110011001100110011001100110011...

In 32-bit floating point it becomes "1.100110011001100110011010b * 2^-4" (which is about 0.10000000149011611938 in decimal).

In 64-bit floating point it becomes "1.10011001100110011001100110011001100110011001100110011b * 2^-4" (which is about 0.099999999999999998612 in decimal).

In 8-bit rational, it becomes "0010b / 0101b" (which is a perfect representation of 0.1).

For the examples above, floating point numbers would need an infinite number of bits just to get close to what rational numbers can do in 8-bits! =D>


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Thomas
Member
Member
Posts: 281
Joined: Thu Jun 04, 2009 11:12 pm

Re: A good maths parser

Post by Thomas »

Hi,
How do you propose to represent irrational numbers , then ?

-- Thomas
User avatar
thepowersgang
Member
Member
Posts: 734
Joined: Tue Dec 25, 2007 6:03 am
Libera.chat IRC: thePowersGang
Location: Perth, Western Australia
Contact:

Re: A good maths parser

Post by thepowersgang »

Thomas wrote:Hi,
How do you propose to represent irrational numbers , then ?

-- Thomas
Closest fraction, of course. They're irrational, unless you are using some form of CAS simplest equation system, they will always be inexact.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Post Reply