A good maths parser
Re: A good maths parser
Hi ,
A simple solution came to my mind . 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
A simple solution came to my mind . 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
Re: A good maths parser
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
--Thomas
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
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: A good maths parser
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".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.
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.
- AndrewAPrice
- Member
- Posts: 2299
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Re: A good maths parser
I'm talking about representing math equations at a higher level, which is nothing to do with decimal precision of the numbers stored.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".
My OS is Perception.
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: A good maths parser
Which is probably not what you want when implementing a compiler or assembler...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.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".
- AndrewAPrice
- Member
- Posts: 2299
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Re: A good maths parser
Unless the compiler happens to be for a functional language such as a Haskel variant.Owen wrote:Which is probably not what you want when implementing a compiler or assembler...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.
My OS is Perception.
Re: A good maths parser
Hi,
2/3 = 667*10^(-3)
667*10^(-3) * 3 = 200*10^(-2) = 2
Now try "((4/3)-1)*3" from my post:
And now with "double":
Now, let's do it with an 8-bit relational numbers (4-bit numerator and 4-bit divisor):
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!
Cheers,
Brendan
That's because the rounding errors cancel each other out. For an example, using three digits: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
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
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
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
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!
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.
Re: A good maths parser
Hi,
How do you propose to represent irrational numbers , then ?
-- Thomas
How do you propose to represent irrational numbers , then ?
-- Thomas
- thepowersgang
- 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
Closest fraction, of course. They're irrational, unless you are using some form of CAS simplest equation system, they will always be inexact.Thomas wrote:Hi,
How do you propose to represent irrational numbers , then ?
-- Thomas
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc