First of all see the following problem:
SetRoundMode(rmUp) and rounding “round” values like 10, results in 10,0001.
I need to round currency values up, so 0.8205 becomes 0.83, but the SimpleRoundTo behavior displayed above is giving me some headaches.
How can I round currency values up in a safe way?
You can use the Ceil function:
newvalue := Ceil(oldvalue * 100) / 100;
Note that rounding 0.8205 up to 0.83, and also rounding 0.8305 up to 0.84, will result in an upward bias on average in your rounding. The default rounding mode is bankers rounding, which rounds towards even numbers to avoid a directional bias.
This is particularly important if there is a double-entry nature to your calculations. Rounding with a directional bias can result in a mismatch on either side.
Using SetRoundMode changes the FPU control word. Be aware that this FPU mode rounding is applied to floating-point operations in situations that might not be obvious when thinking in terms of the Currency type, which is a fixed-point type (scaled 64-bit integer). A small imprecision in intermediate floating-point calculations, such as 82.000000000000001, will end up rounding up even when the value as Currency is anticipated to be 82.00. Changing the thread-global rounding mode is only to be done with caution.
You're doing it wrong.
Don't use floats to represent important types like time and money!
Use integers that represent the highest precision you need. For example use an integer that represents 1000th of a cent. Then you can pass around 82050 around and when you finally need to display it as a string then and only then do you do the rounding using integer calculations.
To actually answer your question, $0.8205 should not be rounded up. $0.825 should be.
Related
I am creating a histogram of an image. I need a way to scale it in y-axis to represent it nicely, as standard image/video processing programs do. Thus I need to make stronger the small values, to make weaker the big values.
What I tried to do so far:
To scale the y-values by dividing them by the greatest y value. It allowed me to see it, but still small values are almost indistinguishable from zero.
What I have seen:
In a standard video processing tool let's say three biggest values have the same y-values on their histogram representation. However, real values are different. And the small values are amplified on the histogram.
I would be thankful for the tips/formula/algorithm.
You can create lookup table (LUT), fill it with values from a curve that describes desired behavior. Seems that you want something like gamma curve
for i in MaxValue range
LUT[i] = MaxValue(255?) * Power(i/MaxValue, gamma)
To apply it:
for every pixel
NewValue = LUT[OldValue]
One column has numbers (always with 2 decimals, some are computed but all multiplications and divisions rounded to 2 decimals), the other is cumulative. The cumulative column has formula =<above cell>+<left cell>.
In the cumulative column the result is 58.78, the next number in the first column is -58.78. Because of different formatting for zero than for positive or negative numbers, I spotted something was wrong. Changing the format to several decimals, the numbers appear as:
£58.780000000000000000000000000000
-£58.780000000000000000000000000000 £0.000000000000007105427357601000
The non-zero zero is about 2^(-47). Another time the numbers in the same situation are:
£50.520000000000000000000000000000
-£50.520000000000000000000000000000 -£0.000000000000007105427357601000
How can that happen?
Also, if I change the cell in cumulative column into the actual number 58.78, the result suddenly becomes zero.
Google Sheets uses double precision floating point arithmetics, which creates such artifacts. The relative precision of this format is 2^(-53), so for a number of size around 2^6 = 64 we expect 2^(-47) truncation error.
Some spreadsheet users would be worried if they found out that "58.78" is actually not 58.78, because this number does not admit an exact representation in this floating point format. So the spreadsheet is hiding the truth, rounding the number for display and printing fake zeros when asked for more digits. Those zeros after 58.78 are fake.
The truth comes to light when you subtract two numbers that appear to be identical but are not — because they were computed in different ways, e.g. one obtained as a sum while the other by direct input. Rounding the result of subtraction to zero would be too much of a lie: this is no longer a matter of a small relative error, the difference between 2^(-47) and 0 may be an important one. Hence the unexpected reveal of the mechanics behind the scenes.
See also: Why does Google Spreadsheets says Zero is not equals Zero?
Consider the really simple difference kernel
kernel vec4 diffKernel(__sample image1, __sample image2)
{
return vec4(image1.rgb - image2.rgb, 1.0);
}
When used as a CIColorKernel, this produces the difference between two images. However, any valus for which image1.rgb < image2.rgb (pointwise) will be forced to zero due to the "clamping" nature of the outputs of kernels in CIKernel.
For many image processing algorithms, such as those involving image pyramids (see my other question on how this can be achieved in Core Image), it is important to preserve these negative values for later use (reconstructing the pyramid, for example). If 0's re used in their place, you will actually get an incorrect output.
I've seen that one such way is to just store abs(image1.rgb - image2.rgb) make a new image, who's RGB values store 0 or 1 whether a negative sign is attached to that value, then do a multiply blend weighted with -1 to the correct places.
What are some other such ways one can store the sign of a pixel value? Perhaps we can use the alpha channel if it being unused?
I actually ended up figuring this out -- you can use an option in CIContext to make sure that things are computed using the kCIFormatAf key. This means that any calculations done on that context will be done in a floating point precision, so that values beyond the scope of [0,1] are preserved from one filter to the next!
I'm doing some calculus on double numbers with 17 numbers after the decimal point.
like 0.1256478965842365987 * 0.125639874569874563
and I get the value named "-inf" when I display it in the console.
What is the signification of that?
It means minus infinity.
EEE 754 floating point numbers can represent positive or negative infinity, and
NaN (not a number). These three values arise from calculations whose result is
undefined or cannot be represented accurately. You can also deliberately set a
floating-point variable to any of them, which is sometimes useful. Some examples
of calculations that produce infinity or NaN:
Now, it is strange that you got that multiplying those two numbers.
I am transforming an image to a frequency spectrum, convolving it with a kernel, then inverse-transforming it back.
I wanted to ask how I can handle the rounding errors which occur during the transformation. Like when I transform an image, then immediately transform it back I have an average PSNR of 127. (I transform the pixels in float format between 0.0 and 1.0.)
Is it possible to calculate the errors and correct them?
Short answer: If you want less rounding error, then you need a more accurate number format. Also, you cannot calculate the error.
More accurate floating-point formats include:
x87 80-bit extended precision (long double)
Fixed point with BigInteger
BigDecimal
Also, isn't a PSNR of 127 dB very good already?