How to find the simplest human-readable float string which would yield the same bytes when converted back to float? - serialization

For most numbers, we know there will be some precision error with any floating point value. For a 32-bit float, that works out the be roughly 6 significant digits which will be accurate before you can expect to start seeing incorrect values.
I'm trying to store a human-readable value which can be read in and recreate a bit-accurate recreation of the serialized value.
For example, the value 555.5555 is stored as 555.55548095703125; but when I serialize 555.55548095703125, I could theoretically serialize it as anything in the range (555.5554504395, 555.555511475) (exclusive) and still get the same byte pattern. (Actually, probably that's not the exact range, I just don't know that there's value in calculating it more accurately at the moment.)
What I'd like is to find the most human-readable string representation for the value -- which I imagine would be the fewest digits -- which will be deserialized as the same IEEE float.

This is exactly a problem which was initially solved in 1990 with an algorithm the creators called "Dragon": https://dl.acm.org/citation.cfm?id=93559
There is a more modern technique from last year which is notably faster called "Ryu" (Japanese for "dragon"): https://dl.acm.org/citation.cfm?id=3192369
The GitHub for the library is here: https://github.com/ulfjack/ryu
According to their readme:
Ryu generates the shortest decimal representation of a floating point
number that maintains round-trip safety. That is, a correct parser can
recover the exact original number. For example, consider the binary
64-bit floating point number 00111110100110011001100110011010. The
stored value is exactly 0.300000011920928955078125. However, this
floating point number is also the closest number to the decimal number
0.3, so that is what Ryu outputs.

Related

Procedure for Arithmetic (Division) in tcl

Need to divide two numbers (can be floating) in tcl and check if the number is an exact multiple.
!($x % $y) doesn't work as the operand expects integers.
Many floating point numbers used on computers are just an approximation of the specified value. So expecting to be able to check if one value is an exact multiple of another value will likely lead to disappointment.
For example: expr {fmod(1, 0.1)} => 0.09999999999999995 because 0.1 cannot be represented exactly in binary floating point format.
I'm afraid you will have to reconsider your requirements.
See also https://en.wikipedia.org/wiki/Floating-point_arithmetic

Convert negative decimal to binary in T-SQL

I have tried to find information and how.
But it did not contain any information that would help.
With T-SQL, I want to convert negative decimal to binary
and convert it back.
Sample value: -9223372036854775543
I try in convert with Calculater this value to Bin result is ...
1000000000000000000000000000000000000000000000000000000100001001
and Convert back to Dec. It's OK.
How i can Convert like this with T-SQL(SQL2008) Script/Function ?
Long time to find information for how to.
Anyone who knows about this, please help.
There is no build in functionality.
for INT and BIGINT you can use CONVERT(VARCHAR(100),CAST(3 AS VARBINARY(100)),2) to get the hex representation as a string. then you can do a simple search replace as every hex digit represents exactly 4 binary digits. However, with values outside of the BIGINT range there is no standard as to how they are represented internally. You might get the right result or not and that behavior might even change between versions.
There is also no standard as to how negative numbers are represented. Most implementations of integers use the two's-complement representation. In that representation the top most bit indicates the sign of the number. How many bits you have is a metter of convention and fully dependent on your environment.
In mathematics -3 woud be -11 in binary and not 11111101.
To solve your problem you can either use a CLR function or you go through your number the old fashioned way:
Is it odd? -> output a 1
Is it even? -> output a 0
integer divide by 2
repeat until the value is 0
This will give you the digits in opposite order, so you have to flip the result. To get the two's-complement representation of a negative number n calculate 1-n, convert the result to binary using the above algorithm but with reversed digits (0 instead of 1 and vice versa). After flipping the digits into the right order prepend with enough 1s to fill your "box".

Accuracy of double Objective-C [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why can't decimal numbers be represented exactly in binary?
When I enter 0.1 as a double value the compiler is adding a tiny value on the end of it that is causing other calculations to go wrong in the program that I am running. My code simply says:
double temp = 0.1;
And I get this in variable viewer:
http://img.skitch.com/20111122-nnrcgi4dtteg8aa3e8926r3fd4.jpg
Does anyone know why this is happening?
Thanks
double is a floating binary point type. In binary, the value of "a half" is 0.1, and the value of "a quarter" is 0.01 etc. There is no way of exactly representing "a tenth" in a finite binary representation, any more than you can exactly represent "a third" in decimal. The compiler is giving you the closest value it can to the value you've actually asked for.
If you want to store decimal values precisely because you care about the decimals (e.g. for current) you should use a decimal-based type such as NSDecimalNumber, or an integer scaled appropriately (e.g. storing 15 for 15 cents instead of 0.15 dollars).
I have articles on binary and decimal floating point in .NET - NSDecimalNumber in Objective-C is slightly different to decimal in C# (see the documentation), but hopefully those articles will give you a bit more insight into what's actually happening.
EDIT: As noted in comments, typically decimal floating point types are significantly slower than binary floating point types, partly because they're often larger and partly because they don't have CPU support. If you have a hard performance requirement and you want to retain digits precisely, the "integer and implied scale" option is usually a good one, though a pain to code against as you need to take it into account every time you read the code :)

1.2 in SQLite3 Database Is Actually 1.199999998

I am attempting to store a float in my SQLite3 database using java. When I go to store the number 1.2 in the database, it is actually stored as 1.199999998 & the same occurs for every even number (1.4, 1.6, etc.).
This makes is really diffult to delete rows because I delete a row according to its version column(whose type =float). So this line wont work:
"DELETE FROM tbl WHERE version=1.2"
Thats because there is no 1.2 but only 1.19999998. How can I make sure that when I store a float in my SQLite3 DB, that it is the exact number I input?
Don't use a float if you need precise accuracy. Try a decimal instead.
Remember that the 1.2 you put in your source code or that the user entered into a textbox and ultimately ended up in the database is actually stored as a binary value (usually in a format known as IEEE754). To understand why this is a problem, try converting 1.2 (1 1/5) to binary by hand (binary .1 is 1/2, .01 is 1/4) and see what you end up with:
1.001100110011001100110011001100110011
You can save time by using this converter (ignore the last "1" that breaks the cycle at the site —its because the converter had to round the last digit).
As you can see, it's a repeating pattern. This goes on pretty much forever. It would be like trying to represent 1/3 as a decimal. To get around this problem, most programming languages have a decimal type (as opposed to float or double) that keeps a base 10 representation. However, calculations done using this type are orders of magnitude slower, and so it's typically reserved for financial transactions and the like.
This is the very nature of floating point numbers. They are not exact.
I'd suggest you either use an integer, or text field to store a version.
You should never rely on the accuracy of a float or a double. A float should never be used for keys in a data base or to represent money.
You should probably use decimal in this case.
Floats are not an accurate data type. They are designed to be fast, have a large range of values, and have a small memory footprint.
They are usually implemented using the IEEE standard
http://en.wikipedia.org/wiki/IEEE_754-2008
As Joel Coehoorn has pointed out, 1.2 is the recurring fraction 1.0011 0011 0011... in binary and can't be exactly represented in a finite number of bits.
The closest you can get with an IEEE 754 float is 1.2000000476837158203125. The closest you can get with a double is 1.1999999999999999555910790149937383830547332763671875. I don't know where you're getting 1.199999998 from.
Floating-point was designed for representing approximate quantities: Physical measurements (a swimming pool is never exactly 1.2 meters deep), or irrational-valued functions like sqrt, log, or sin. If you need a value accurate to 15 significant digits, it works fine. If you truly need an exact value, not so much.
For a version number, a more appropriate representation would be a pair of integers: One for the major version and one for the minor version. This would also correctly handle the sequence 1.0, 1.1, ..., 1.9, 1.10, 1.11, which would sort incorrectly in a REAL column.

Objective C Math Formula Fail

noob here wants to calculate compound interest on iPhone.
float principal;
float rate;
int compoundPerYear;
int years;
float amount;
formula should be: amount = principal*(1+rate/compoundPerYear)^(rate*years)
I get slightly incorrect answer with:
amount = principal*pow((1+(rate/compoundPerYear)), (compoundPerYear*years));
I'm testing it with rate of .1, but debugger reports .100000001 .
Am I doing it wrong? Should I use doubles or special class (e.g., NSNumber)?
Thanks for any other ideas!
After further research it seems that the NSDecimalNumber class may be just what I need. Now I just have to figure out how to use this bad boy.
double will get you closer, but you can't represent 1/10 exactly in binary (using IEEE floating point notation, anyway).
If you're really interested, you can look at What Every Computer Scientist Should Know About Floating-Point Arithmetic. Link shamefully stolen from another SO thread.
The quick and dirty explanation is that floating point is stored in binary with bits that represents fractional powers of 2 (1/2, 1/4, 1/8, ...). There is simply no mathematical way to add up these fractions to exactly 1/10, thus 0.1 is not able to be exactly represented in IEEE floating point notation.
double extends the accuracy of the number by giving you more numerals before/after the radix, but it does not change the format of the binary in a way that can compensate for this. You'll just get the extra bit somewhere later down the line, most likely.
See also:
Why can’t decimal numbers be represented exactly in binary?
What’s wrong with using == to compare floats in Java?
and other similar threads.
Further expansion that I mulled over on the drive home from work: one way you could conceivably handle this is by just representing all of the monetary values in cents (as an int), then converting to a dollars.cents format when displaying the data. This is actually pretty easy, too, since you can take advantage of integer division's truncating when you convert:
int interest, dollars, cents;
interest = 16034; //$160.34, in cents
dollars = value / 100; //The 34 gets truncated: dollars == 160
cents = value % 100; //cents == 34
printf("Interest earned to date: $%d.%d\n", dollars, cents);
I don't know Objective-C, but hopefully this C example makes sense, too. Again, this is just one way to handle it. It would also be improved by having a function that does the string formatting whenever you need to show the data.
You can obviously come up with your own (even better!) way to do it, but maybe this will help get you started. If anyone else has suggestions on this one, I'd like to hear them, too!
Short answer: Never use floating point numbers for money.
The easy way that works across most platforms is to represent money as integer amounts of its smallest unit. The smallest unit is often something like a cent, although often 1/10 or 1/100 of a cent are the real base units.
On many platforms, there are also number types available that can represent fixed-point decimals.
Be sure to get the rounding right. Financial bookkeeping often uses banker's rounding.