![]() |
.NET database and distributed computing tools |
The Base/1 Number Class is a software product that enables you to improve the accuracy of arithmetic in any C++ application. While C++ has become the tool of choice for building all types of applications, it still suffers from limitations that can be traced to its roots as a scientific programming language for minicomputers. For example, C++ lacks features supporting high-precision decimal arithmetic, which have long existed on mainframe computers because of their orientation toward large-scale business applications. Base One's Number Class fills this gap, bringing the power and convenience of mainframe computing to C++ programmers.
Although C/C++'s native numeric data types, Int, Double, Float, Long, etc. work fine in many situations, their underlying binary representation and limited precision present problems that become more apparent as the number of significant digits increases. Thus for example one loses accuracy because of rounding, or worse, results can be grossly in error because of failure to detect the truncation of high-order digits in a calculation that produces an overflow.
While these shortcomings of C/C++ can be overcome with extra programming effort, one must be diligent, and it's easy to make subtle mistakes that don't show up for years. But the beauty of C++ is that it allows you to solve a problem once and reuse that solution from then on. That's exactly what we've done in the Base/1 Number Class, which includes fully documented ANSI/C++ source code and everything you need to write more accurate programs on any platform.
Because it addresses such a fundamental and general language feature, the Base/1 Number Class applies to a wide range of application types:
The most compelling candidates for the Number Class share one or more of these requirements:
Consider, for example, how some typical applications might be driven to need the additional accuracy afforded by Base One's Number Class.
A currency trading system has been working fine for years, and the company that uses it is growing successfully. Suddenly they cross a threshold, where the cash balance of an account (in Japanese Yen) reaches too large a value to display in an important report. They fix the report, but other errors start to crop up and getting accounts to balance is becoming a programming headache. Unexpected delays and embarrassing complaints from customers grow more frequent. Eventually, the problem spreads from isolated reports to deeper troubles in core analysis programs and database structures. Then the whole system goes down, and the MIS department says it's going to require a major rewrite. The problem they've come up against can no longer be fixed by simple localized adjustments, and it all boils down to the inherent inaccuracy of working with decimal fractions as binary numbers.
An engineering firm is developing a new generation of laser-based telemetry product, which depends on extremely precise measurements of minute differences between large numbers. Thanks to a breakthrough in their research, they've come up with a way of increasing the accuracy of their device by several orders of magnitude. They've invested years of programming developing a fast, computationally intensive program that could be logically extended to cope with greater precision. But while the basic algorithm is still sound, the current program design uses standard C++ double precision floating point numbers, and there's no room to store the extra digits they will need to the right of the decimal point. Now they face the prospect of a total rewrite in order to switch to a different representation of numbers throughout their program, and they are concerned that their product's reputation for speed will suffer in the process.
In each of these scenarios the Base/1 Number Class may be the best solution, because it supports increased accuracy efficiently and with minimal programming.
Whether you're creating a new application or converting an existing one, using the Base/1 Number Class is about as easy as you could ask. All that's required is to include the Number Class header file and declare your number variables as instances of the Number Class instead of using C++ native data types like Int, Float, Double, Long, etc. Through its use of overloaded operators the Number Class provides the same convenience as C++'s built-in data types. This means that no reprogramming is necessary for all of your existing code that works with numbers, performing arithmetic operations, passing arguments, doing assignments, etc.
By default the Base/1 Number Class assumes a precision and scale (38, 8) sufficient to handle the largest DBMS-supported numeric fields. This is more than enough to handle the 16-digit limit of C++'s double data type, so you can make a direct substitution without any further programming changes. That gives you 8 digits to the right of the decimal point and 30 (38 - 8) digits to the left of decimal point, which is ample for most purposes. If you need to get this much accuracy out of C++ you're out of luck, but with the Base/1 Number Class you can simply adjust the declaration to allow up to 100 significant digits, placing the decimal point at any desired position.
Even if you don't need that kind of precision, Base One's Number Class makes it easier to write reliable applications by adding convenient error-trapping features. This covers errors like Overflow, Divide by zero, Invalid sign, etc., which are not handled automatically by C++. (For more, see Sample Number Class Usage)
No. The Base/1 Number Class is independent of all platforms and operating systems because it is written in ANSI standard C++ and uses the Standard Template Library (STL). It can be used in various environments like DOS, Windows, UNIX, LINUX, etc., all of which have a standard ANSI/C++ compiler. However, we test only on Win32 platforms, with MS Visual C++, and supply only those makefiles. We've been careful to use only the most basic C++ features and the standard, public STL interface. In addition, we have upgraded the source code whenever developers have reported minor compilation errors when working with non Microsoft compilers. This means that you can develop portable, cross-platform applications using Base One's Number Class.
Yes. The Base/1 Number Class is compatible with both the Microsoft Foundation Classes (MFC) and the Standard Template Library (STL). You can use the Base/1 Number Class whether you write Windows/MFC programs with Microsoft's Visual C++ or you program for an STL environment like Unix, using ANSI/C++. The sample code that ships with the product includes MFC and STL based projects, which both execute the same examples of Number Class usage. (With the Number Class source code, we supply a small string class, clsStrPlus, as a layer between the Number Class and raw MFC and STL strings, and this string class can be easily adapted to handle any peculiarities of the particular STL implementation being used.)
The Base/1 Number Class uses an innovative variable-length encoding of numbers that bears some resemblance to Binary Coded Decimal (BCD), but is considerably more efficient in several respects. One of the keys to Base One's unique patented design is its use of fast, robust STL/MFC string classes to maintain the internal representation of numbers. This design makes possible a number of features not found in other numeric encoding technologies:
Since we provide the full source code with extensive comments, documentation, and examples, you can learn as much as you want to about our approach. Students of Computer Science who are interested in data structures and algorithms can greatly benefit from the Base/1 Number Class because few, if any, books on the market cover precision arithmetic in such detail.
Several points about the design of the Base/1 Number Class contribute to its ability to precisely represent very large and very small numbers in a minimum amount of space:
Besides simply saving space, the compactness of Base One's Number Class representation provides a performance boost by shortening in-memory data transfers and reducing the amount of disk I/O. But there are additional reasons for significant speedups owing to the unique design of the Base/1 Number Class:
C++ provides only minimal facilities for detecting and handling errors that can occur in numeric arithmetic and conversion operations. This makes it necessary for programmers to take extra steps to be sure that certain errors, such as division by zero and overflow, can not occur. Otherwise, a program may crash or simply yield incorrect results when one of these exceptional conditions arises. All too often obscure bugs result from failing to add adequate error checking logic, because this is generally viewed by programmers as an annoying detail. The Base/1 Number Class provides additional capabilities for detecting and handling errors, so these details don't burden the programmer but they also don't get overlooked:
Over the years of testing of the Number Class, we've discovered nasty bugs in Microsoft's fmod() function, which you can easily confirm for yourself. For example, using the Windows 95 Calculator accessory (evidently built on the same fmod function) try this simple calculation:
Instead of giving the correct result, which should be 0, it shows the result as 1.1. Similar errors are not hard to find, e.g. try 5.1 mod 1.7, 49 mod 9.8, 21.9 mod 7.3, and 36 mod 7.2. Interestingly, this problem occurs only with certain choices of values and the pattern of failures is not trivially discerned, but there are obviously many more cases. In fact we found it increasingly rare not to encounter such errors with more decimal places. We were unable to find any reference to this disturbing bug in the Microsoft Knowledge Base.
Considering how much flack Intel took over an even more obscure arithmetic bug in its Pentium processor, one can only wonder how Microsoft ever got away with this one. Fortunately, the problem seems to have been quietly fixed in Windows 98, but that's not much consolation to those of us who expect our programs to work properly under Windows 95 and early versions of Windows NT 4.0. In any case, rest assured that the Base/1 Number Class computes the modulo function correctly under any version of Windows.
The modulo bug described above seems to have been fixed in the latest operating systems and service packs from Microsoft. However, here's a new one we discovered in recent testing of the Number Class:
d1 = 8853.41959899;
d2 = 2951.13986633;
fmod( d1, d2 ) returns the same value as that of d2 instead of returning zero. In this example, d1 is a perfect multiple of d2 (d1 = d2 * 3). We got this error on Windows NT Service Pack 5 and 6a and Windows 2000 server. For some versions, the bug did NOT appear in the calculator program, but using fmod() ALWAYS produces this bug. The Number Class properly returns the correct remainder of zero.
If you build database applications, the Base/1 Number Class provides additional benefits whether you use a standard relational database management system (RDBMS), an object-oriented database, ISAM, or flat files to store your data. Besides its general compactness and speed, the Number Class addresses the following issues of importance to designers of information storage and retrieval systems:
For users of Base/1 Foundation Component Library (BFC), a further advantage of the Base/1 Number Class is its total integration with BFC's data dictionary and database retrieval and modification operations. Numbers can be stored into and retrieved from database records directly using Number Class variables. Also Number Class instances can be initialized to the attributes of a database field defined in the data dictionary, including length (precision), scale, and a formatting mask to be used for display and/or data entry. For example, if you know that a calculated value will end up being stored in a particular field, initializing the number with that field's name will automatically insure that its length and scale will be the basis for proper rounding behavior and for generating overflow error notification when appropriate limits have been exceeded.
No. All you need is an ANSI-compatible C++ compiler. While the Number Class is a component of the Base/1 Foundation Component Library (BFC), the system's modular design allows us to sell it as a separate product. There is nothing about the Base/1 Number Class that depends on BFC. If you have BFC, you do not need to buy the Number Class separately, because BFC includes it.
Thanks to Base One's design based on operator overloading, using the Number Class is virtually identical to using built-in C++ number types. The usual arithmetic operators, assignment statements, parameter passing, etc. work with Number Class variables just as they work with standard C++ numbers. And because of Reference Counting, the overhead of using the Number Class is comparable to that of standard C++ data types, so it can be used freely without having to be conscious that it is a user-defined C++ class. But the Number Class has significant advantages over native C++ number types due to these fundamental differences:
Microsoft provides a data type called "CURRENCY" as part of its OLE (Object Linking & Embedding) technology. To use it in a C++ application, you need to use MFC, which provides a C++ class called COleCurrency. (In Visual Basic this number type is called VB Currency.) COleCurrency behaves like a 64-bit integer with automatic scaling to support 4 digits to the right of the decimal point. While this is a little more convenient than resorting to manual scaling of C++'s basic integer data type, it still suffers from a number of drawbacks:
The Base/1 Number Class has none of these limitations. It can be used just like any native C++ number type, and calculations are much less restricted in both precision and scale than those of either C++ or COleCurrency. A Number Class variable can be used freely with any of the standard C++ number types to perform arithmetic, or both the operands can be of Number Class type (which is not possible with COleCurrency for multiplication and division).
The problem of dealing with numbers that don't fit into 64 bits is not a new one. For decades programmers of IBM mainframe computers have used variations of Binary Coded Decimal or "packed decimal" numeric encodings to cope with long numbers, supported not only by most mainframe programming languages, but right down to the hardware. The C/C++ programming language and most modern microprocessors, however, do not support packed decimal arithmetic.
Packed decimal numbers are reasonably compact because they store 2 decimal digits in each 8-bit byte, i.e. 1 digit per 4-bit "nibble", using either a fixed-length or a variable-length encoding. There is no explicit decimal point, and the rightmost nibble is used to store a sign. For fixed-length numbers, the scale (i.e. the placement of the decimal point) is determined by a declaration statement in the program. Variable-length packed decimal stores the total length and scale in the first byte of the number.
The Base/1 Number Class is similar to variable-length packed decimal in that it also stores 2 decimal digits per byte and can represent numbers of varying length and scale. But Base One's innovative encoding is fundamentally different from packed decimal and other variants of BCD, giving the Number Class several major advantages:
Rogue Wave used to sell a C++ class library called Money.h++ that also supported extended precision decimal arithmetic. According to Rogue Wave's web site, the ".h++ product line entered into obsolescence effective May 1, 2001". Because Base One's Number Class uses standard C++ arithmetic syntax, it's easy to migrate applications off of Money.h++.
Both Money.h++ and the Base/1 Number Class have a number of features in common:
However, there are a number of significant differences between Rogue Wave's Money.h++ and Base One's Number Class, due to their entirely different internal representation of numbers. Rogue Wave's approach provides separate fixed and floating decimal point classes in 16 different precisions, with each variation requiring a certain fixed-size allocation. Base One's approach uses a single number class that inherently supports a floating decimal point and variable precision, with no fixed-size minimum allocation. Rogue Wave claims that Money.h++ offers the "convenience of BCD", but the unique properties of Base One's innovative design give our Number Class these important advantages:
The Number Class is just a small (operating system independent) part of Base One's Foundation Component Library (BFC), which is designed for building business systems with Visual C++ and MFC. If you use BFC, there are other C++ classes available to speed development of financial applications. For example, the Mask Class provides number formatting that handles internationalization issues like currency and the characters for decimal point and thousands separator. (The default characters to be used for currency, decimal point and thousands separator are obtained from Control Panel/Regional Settings, as stored in the Win.ini file). However, the Number Class by itself is all that is needed for the efficient, accurate, decimal arithmetic required for developing sophisticated financial applications.
Even if you already own and use Rogue Wave's products, you'll find the Base/1 Number Class to be an indispensable tool to add to your arsenal, at an unbeatable price.
Number Class Intro | Overview | FAQ | Representation | Algorithms | Sample Usage | Prices
|
|||||||
Home | Products | Consulting | Case Studies | Order | Contents | Contact | About Us |
|
|||||||
Copyright © 2012, Base One International Corporation |