Use Hashing function to validate floating point calculations [duplicate] - validation

This question already has answers here:
Floating point arithmetic and reproducibility
(1 answer)
Reproducibility of floating point operation result
(2 answers)
Is specifying floating-point type sufficient to guarantee same results?
(1 answer)
Closed 1 year ago.
Hash functions like SHA-2 are widely used to validate the transfer of data or to validate cryptographic integer calculations.
Is it possible to use hash functions to validate floating point calculations, e.g. a physics simulation. In other words is it possible and viable to make floating point calculations consistent across multiple platforms?
If the answer to the previous question is "no", given the calculations are carefully crafted, it might be possible to hash data with reduced precision and still get high confidence in the validation. Is there any ongoing project which tries to achieve that?

Hashes work on binary input, usually bytes. So if you want to use hashes to compare results instead of comparing the results themselves then you need to create a canonical binary encoding of the values. For floating point, the common standard that specifies how numbers can be encoded is IEEE 754, and most languages will specify how they use floats compared to that standard.
For instance, Java adheres to the "round-to-nearest rule of IEEE 754 floating-point arithmetic" and starts with this part:
The floating-point types are float and double, which are conceptually associated with the single-precision 32-bit and double-precision 64-bit format IEEE 754 values and operations as specified in IEEE Standard for Binary Floating-Point Arithmetic, ANSI/IEEE Standard 754-1985 (IEEE, New York).
Please that you should also understand the strictfp flag for Java. Similar tricks may be required for other languages as well.

Related

Should I use double data structure to store very large Integer values?

int types have a very low range of number it supports as compared to double. For example I want to use a integer number with a high range. Should I use double for this purpose. Or is there an alternative for this.
Is arithmetic slow in doubles ?
Whether double arithmetic is slow as compared to integer arithmetic depends on the CPU and the bit size of the integer/double.
On modern hardware floating point arithmetic is generally not slow. Even though the general rule may be that integer arithmetic is typically a bit faster than floating point arithmetic, this is not always true. For instance multiplication & division can even be significantly faster for floating point than the integer counterpart (see this answer)
This may be different for embedded systems with no hardware support for floating point. Then double arithmetic will be extremely slow.
Regarding your original problem: You should note that a 64 bit long long int can store more integers exactly (2^63) while double can store integers only up to 2^53 exactly. It can store higher numbers though, but not all integers: they will get rounded.
The nice thing about floating point is that it is much more convenient to work with. You have special symbols for infinity (Inf) and a symbol for undefined (NaN). This makes division by zero for instance possible and not an exception. Also one can use NaN as a return value in case of error or abnormal conditions. With integers one often uses -1 or something to indicate an error. This can propagate in calculations undetected, while NaN will not be undetected as it propagates.
Practical example: The programming language MATLAB has double as the default data type. It is used always even for cases where integers are typically used, e.g. array indexing. Even though MATLAB is an intepreted language and not so fast as a compiled language such as C or C++ is is quite fast and a powerful tool.
Bottom line: Using double instead of integers will not be slow. Perhaps not most efficient, but performance hit is not severe (at least not on modern desktop computer hardware).

What is the range of a VHDL integer definition VHDL-2019?

While using the VHDL-2019 IEEE spec
section. 5.2.3.1. General
"However, an implementation shall allow the declaration of any integer
type whose range is wholly contained within the bounds –(2**63) and
(2**63)–1 inclusive."
(I added the exponential **)
Does this mean –(2**63) = -9223372036854775808 ?
In the 1993 spec it states -((2**31) - 1) and (2**31) - 1)
-2147483647 & 2147483647
Does the new VHDL spec have an error in that definition?
Ken
The change is quite intentional. See LCS2016_026c. You could note this gives the same range as a 64 bit integer in programming languages. The non-symmetrical effect comes from two's complement numbers which are the basis of integer types in VHDL tool implementations, the age of big iron with decimal based ALUs long faded.
The previous symmetrical range was not an implementation concern, VHDL arithmetic semantics requires run time detection of rollover or underflow. This change allows simpler detection based on changing signs without testing values while performing arithmetic in yet a larger than 64 bits universal integer.
The value range increase is an attempt to force synthesis vendors to support more than the minimum range specified in previous editions of the the standard. How well that works out (and over what implementation interval) will be a matter of history at some future date. There are also secondary effects based on index ranges (IEEE Std 1076-2019 5.3.2.2 Index constraints and discrete ranges) and positional correspondence for enumerated types (5.2.2 Enumerated types, 5.2.2.1 General). It's not practicable to simulate (or synthesize) composite objects with extreme index value ranges, starting with stack size issues. Industry practice isn't settled, and likely may result in today's HDLs being obsoleted.
Concerns to the accuracy of the standard's semantic description can be addressed to the IEEE-SAs VASG subcommittee which encourages participation by interested parties. You will find Stackoverflow vhdl tag denizens here who have been involved in the standardization process.

Go Protobuf Precision Decimals

What is the correct scalar type to use in my protobuf definition file, if I want to transmit an arbitrary-precision decimal value?
I am using shopspring/decimal instead of a float64 in my Go code to prevent math errors. When writing my protobuf file with the intention of transmitting these values over gRPC, I could use:
double which translates to a float64
string which would certainly be precise in its own way but strikes me as clunky
Something like decimal from mgravell/protobuf-net?
Conventional wisdom has taught me to skirt floats in monetary applications, but I may be over-careful since it's a point of serialization.
If you really need arbitrary precision, I fear there is no correct answer right now. There is https://github.com/protocolbuffers/protobuf/issues/4406 open, but it does not seem to be very active. Without built-in support, you will really need to perform the serialization manually and then use either string or bytes to store the result. Which one to use between string and bytes likely depends on whether you need cross-platform/cross-library compatibility: if you need compatibility, use string and parse the decimal representation in the string using the appropriate arbitrary precision type in the reader; if you don't need it and you're going to read the data using the same cpu architecture and library you can probably just use the binary serialization provided by that library (MarshalBinary/UnmarshalBinary) and use bytes.
On the other hand, if you just need to send monetary values with an appropriate precision and do not need arbitrary precision, you can probably just use sint64/uint64 and use an appropriate unit (these are commonly called fixed-point numbers). To give an example, if you need to represent a monetary value in dollars with 4 decimal digits, your unit would be 1/10000th of a dollar so that e.g. the value 1 represents $0.0001, the value 19900 represents $1.99, -500000 represents $-50, and so on. With such a unit you can represent the range $-922,337,203,685,477.5808 to $922,337,203,685,477.5807 - that should likely be sufficient for most purposes. You will still need to perform the scaling manually, but it should be fairly trivial and portable. Given the range above, I would suggest using sint64 is preferable as it allows you also to represent negative values; uint64 should be considered only if you need the extra positive range and don't need negative values.
Alternatively, if you don't mind importing another package, you may want to take a look at https://github.com/googleapis/googleapis/blob/master/google/type/money.proto or https://github.com/googleapis/googleapis/blob/master/google/type/decimal.proto (that incidentally implement something very similar to the two models described above), and the related utility functions at https://pkg.go.dev/github.com/googleapis/go-type-adapters/adapters
As a side note, you are completely correct that you should almost never use floating point for monetary values.

Representing a fraction in binary?

I'm looking at binary data representations for fractions, and I was wondering what kind of a data structure the fraction would have if you were to store both the numerator and denominator that store a fraction. Is it just two separate numbers that have no relation but are combined when used in a calculation?
If you want to store rational numbers without losing precision the correct way is to store both the numerator and denominator.
In practice most people use either floating-point math or built-in/library arbitrary-precision number data-types (e.g. Java's BigDecimal).
If you specifically want to use a data-type for fractions, some languages have built-in types for rational numbers. For most other languages there is usually a library with a usable datatype (e.g. for Java Apache Commons has a Fraction class and for C/C++ GMP has a mpq_t datatype)

Arbitrary base conversion algorithm for (textually represented) integers

I am looking a general algorithm that would convert from one (arbitrary) numerical base to another (also arbitrary) without storing the result in a large integer and performing arithmetic operations on it in between.
The algorithm I am looking for takes an array of numerical values in a given base (that would mostly be a string of characters) and returns the result alike.
Thank you for help.
I would say it is not possible. For certain bases it would be possible to convert from one string to another, by just streaming the chars through (e.g. if one base is a multiple of the other, like octal->hex), but for arbitrary bases it is not possible without arithmetic operations.
If you would do it with strings/chars in between it would be still big integer arithmetic, but your integers were just in a (unnecessary big) unusual format.
So you have just the choice between: Either reprogram arithmetic operations with char encoded numbers, or do the step and use a big integer library and walk the convert(char(base1->bigInt), convert(bigInt->base2) path.
It's computable, but it's not pretty.
Seriously, it'd probably be easier and faster to include one of the many bignum libraries or write your own.

Resources