Out of range value for column in MySQL float column - mysql

I have a MySQL database with a table containing many columns declared as float type, e.g.TgPhi_L1_Min FLOAT DEFAULT NULL,. The table is filled by a program written in C++Builder 10.3 using FireDAC (TFDQuery) that collects data from a measuring device. The code responsible for that looks like this:
FDQuery_InsertData->Open("SELECT * FROM {id measurements_general} WHERE 1=2");
FDQuery_InsertData->Insert();
FDQuery_InsertData->FieldByName("meter_id")->AsInteger = MeterId;
FDQuery_InsertData->FieldByName("cfg_id")->AsInteger = ConfigId;
FDQuery_InsertData->FieldByName("date_time")->AsDateTime = DateTime;
FDQuery_InsertData->FieldByName("insert_date_time")->AsDateTime = Now();
for (auto i = 0; i < DescriptorsGeneral.List->Count; i++)
{
if (IsNan(Data[DescriptorsGeneral.Indexes[i]]) || IsInfinite(Data[DescriptorsGeneral.Indexes[i]]))
continue;
FDQuery_InsertData->FieldByName(DescriptorsGeneral.List->Strings[i])->AsSingle = Data[DescriptorsGeneral.Indexes[i]]; //Data is passed as a parameter to this function, float *Data;
}
FDQuery_InsertData->Post();
Everything goes fine, until someday a measuring device sent a value which is the maximum float value of 0x7F7FFFFF. It shouldn't be a problem, but I got an exception
First chance exception at $772A3642. Exception class EMySQLNativeException with message '[FireDAC][Phys][MySQL] Out of range value for column 'TgPhi_L1_Min' at row 1'. Process Meter_Server.exe (12796).
Trying to understand what happened, I turned on FireDAC's monitor, and it turns out that the value inserted into the INSERT statement indeed exceeds the float range i.e. 3.4028235E38. What I find more surprising is that numbers passed to the INSERT statement differ in precision, although all are declared the same way (MySQL float, FireDAC single), eg 0.98364758, 0, 3.4028235E38, -3.4028235E38, 0, 3.4028235E38, -3.4028235E38, 29.885546.
The parameters of fetching columns by TFDQuery are: Col add [Index=86, SrcName="TgPhi_L1", SrcType=Single, SrcSize=0, SrcPrec=12, SrcScale=31, Type=Single, Size=0, Prec=12, Scale=31].
I tried with FormatOptions: CheckPrecision and Round2Scale, I added my own mapping rules setting ScaleMin and PrecMin, but none of it affected values in the INSERT statement sent to the database by FireDAC.
Can anyone help me solve this problem? what I am doing wrong?
EDITED:
I'm confused, of course when I prepare a proper string manually, as #GarrGodfrey suggested, it works, but it doesn't work with TFDQuery in the way I did it. TFDQuery knows that the field is the single type, and finally always converts and rounds the values to single precision. The problem is, the single type fields have a Precision property set to 7, which complies with the float standard. But in MySQL I'm not sure, this is where I'm lost.
In C++, the following two numbers are treated as equal:
float x = 3.4028235E38;
float y = 3.402823466385288E38;
I think, this is because y has much more precision and is rounded. In MySQL, these are two different numbers: x is out of range and y is not, why?
CREATE PROCEDURE `test_float`()
begin
declare x float;
declare y float;
set x = 3.4028235E38;
set y = 3.402823466385288E38;
select x, y;
end

Related

What happens when you pass an expression to a function which has passing by value-result?

I'm attending a course of principles of programming languages and there's this exercise where I'm supposed to tell what gets printed by this program:
{
int x=2;
void A (val/res int y)
{
x++;
write(y);
y=y+2;
}
A(x)
A(x+1)
write (x);
}
A is a function with value/result parameters passing, so right before returning it should copy the final value of its formal parameter (y) in the actual parameter. When A first gets called its actual parameter is x, so there's no problem there. However, the second call to A has x+1 as the actual parameter.
What does that mean? Maybe the final value of y gets lost because there's no variable where to copy it? Or maybe I should consider it like an equation, so if the final value of y is 7 I get that x + 1 = 7, and then the value of x is 6?
It means the value of the argument is copied to y:
When x=2, A(x) copies 2 to y at the start of A
When x=4, A(x+1) copies the value of x+1, or 5, to y at the start of A
However, as you pointed, out, passing x+1 for a value/result parameter is problematic, and I would expect any language supporting this type of parameter would not consider it legal, for just the reason you cite. If it is considered legal, how it is accomplished would be up to the language definition; I do not believe there is a standard way to handle this.

Octave keeps giving results from function although not asked

I created a function in Octave for which I, at this moment, only want one of the possible outputs displayed. The code:
function [pi, time, numiter] = PageRank(pi0,H,v,n,alpha,epsilon);
rowsumvector=ones(1,n)*H';
nonzerorows=find(rowsumvector);
zerorows=setdiff(1:n,nonzerorows); l=length(zerorows);
a=sparse(zerorows,ones(l,1),ones(l,1),n,1);
k=0;
residual=1;
pi=pi0;
tic;
while (residual >= epsilon)
prevpi=pi;
k=k+1;
pi=alpha*pi*H + (alpha*(pi*a)+1-alpha)*v;
residual = norm(pi-prevpi,1);
end
pi;
numiter=k
time=toc;
endfunction
Now I only want numiter returned, but it keeps giving me back pi as well, no matter whether I delete pi;, or not.
It returns it in the following format:
>> PageRank(pi0,H,v,length(H),0.9,epsilon)
numiter = 32
ans =
0.026867 0.157753 0.026867 0.133573 0.315385
To me it seems strange that the pi is not given with its variable, but merely as an ans.
Any suggestions?
I know the Octave documentation for this is not very extensive, but perhaps it gives enough hints to understand that how you think about output variables is wrong.
The call
PageRank(pi0,H,v,length(H),0.9,epsilon)
returns a single output argument, it is equivalent to
ans = PageRank(pi0,H,v,length(H),0.9,epsilon)
ans is always the implied output argument if none is explicitly given. ans will be assigned the value of pi, the first output argument of your function. The variable pi (nor time, nor numiter) in your workspace will be modified or assigned to. These are the names of local variables inside your function.
To obtain other output variables, do this:
[out1,out2,out3] = PageRank(pi0,H,v,length(H),0.9,epsilon)
Now, the variable out1 will be assigned the value that pi had inside your function. out2 will contain the value of time, and out3 the value of numiter,
If you don't want the first two output arguments, and only want the third one, do this:
[~,~,out3] = PageRank(pi0,H,v,length(H),0.9,epsilon)
The ~ indicates to Octave that you want to ignore that output argument.

How to optimize finding values in 2D array in verilog

I need to set up a function that determines if a match exists in a 2D array (index).
My current implementation works, but is creating a large chain of LUTs due to if statements checking each element of the array.
function result_type index_search ( index_type index, logic[7:0] address );
for ( int i=0; i < 8; i++ ) begin
if ( index[i] == address ) begin
result = i;
end
end
Is there a way to check for matches in a more efficient manner?
Not much to be done, really; at least for the code in hand. Since your code targets hardware, to optimize it think in terms of hardware, not function/verilog code.
For a general purpose implementation, without any known data patterns, you'll definitely need (a) N W-bit equality checks, plus (b) an N:1 FPA (Fixed Priority Arbiter, aka priority encoder, aka leading zero detector) that returns the first match, assuming N W-bit inputs. Something like this:
Not much optimization to be done, but here are some possible general-purpose optimizations:
Pipelining, as shown in the figure, if timing is an issue.
Consider an alternative FPA implementation that makes use of 2's complement characteristics and may result to a more LUT-efficient implementation: assign fpa_out = fpa_in & ((~fpa_in)+1); (result in one-hot encoding, not weighted binary, as in your code)
Sticking to one-hot encoding can come in handy and reduce some of your logic down your path, but I cannot say for sure until we see some more code.
This is what the implementation would look like:
logic[N-1:0] addr_eq_idx;
logic[N-1:0] result;
for (genvar i=0; i<N; i++) begin: g_eq_N
// multiple matches may exist in this vector
assign addr_eq_idx[i] = (address == index[i]) ? 1'b1 : 1'b0;
// pipelined version:
// always_ff #(posedge clk, negedge arstn)
// if (!arstn)
// addr_eq_idx[i] <= 1'b0;
// else
// addr_eq_idx[i] <= (address == index[i]) ? 1'b1 : 1'b0;
end
// result has a '1' at the position where the first match is found
assign result = addr_eq_idx & ((~addr_eq_idx) + 1);
Finally, try to think if your design can be simplified due to known run-time data characteristics. For example, let's say you are 100% sure that the address you're looking for may exist within the index 2D array in at most one position. If that is the case, then you do not need an FPA at all, since the first match will be the only match. In that case, addr_eq_idx already points to the matching index, as a one-hot vector.

Format number with variable amount of significant figures depending on size

I've got a little function that displays a formatted amount of some number value. The intention is to show a "commonsense" amount of significant figures depending on the size of the number. So for instance, 1,234 comes out as 1.2k while 12,345 comes out as 12k and 123,456 comes out as 123k.
So in other words, I want to show a single decimal when on the lower end of a given order of magnitude, but not for larger values where it would just be useless noise.
I need this function to scale all the way from 1 to a few billion. The current solution is just to branch it:
-- given `current`
local text = (
current > 9,999,999,999 and ('%dB') :format(current/1,000,000,000) or
current > 999,999,999 and ('%.1fB'):format(current/1,000,000,000) or
current > 9,999,999 and ('%dM') :format(current/1,000,000) or
current > 999,999 and ('%.1fM'):format(current/1,000,000) or
current > 9,999 and ('%dk') :format(current/1,000) or
current > 999 and ('%.1fk'):format(current/1,000) or
('%d'):format(current) -- show values < 1000 floored
)
textobject:SetText(text)
-- code formatted for readability
Which I feel is very ugly. Is there some elegant formula for rounding numbers in this fashion without just adding another (two) clauses for every factor of 1000 larger I need to support?
I didn't realize how simple this actually was until a friend gave me a solution (which checked the magnitude of the number based on its length). I converted that to use log to find the magnitude, and now have an elegant working answer:
local suf = {'k','M','B','T'}
local function clean_format(val)
if val == 0 then return '0' end -- *Edit*: Fix an error caused by attempting to get log10(0)
local m = math.min(#suf,math.floor(math.log10(val)/3)) -- find the magnitude, or use the max magnitude we 'understand'
local n = val / 1000 ^ m -- calculate the displayed value
local fmt = (m == 0 or n >= 10) and '%d%s' or '%.1f%s' -- and choose whether to apply a decimal place based on its size and magnitude
return fmt:format(n,suf[m] or '')
end
Scaling it up to support a greater factor of 1000 is as easy as putting the next entry in the suf array.
Note: for language-agnostic purposes, Lua arrays are 1-based, not zero based. The above solution would present an off-by-one error in many other languages.
Put your ranges and their suffixes inside a table.
local multipliers = {
{10^10, 'B', 10^9},
{10^9, 'B', 10^9, true},
{10^7, 'M', 10^6},
{10^6, 'M', 10^6, true},
{10^4, 'k', 10^3},
{10^3, 'k', 10^3, true},
{1, '', 1},
}
The optional true value at the 4th position of alternate variables is for the %.1f placeholder. The third index is for the divisor.
Now, iterate over this table (using ipairs) and format accordingly:
function MyFormatter( current )
for i, t in ipairs( multipliers ) do
if current >= t[1] then
local sHold = (t[4] and "%.1f" or "%d")..t[2]
return sHold:format( current/t[3] )
end
end
end

How to set Nodata value into zero

I have a question. How can I set null value into 0 on an image. Is there any way to do this in matlab. The image type is float-point, 32 bit, tif format. Null value (Nodata) of this image is -3.4028234663e+038. So the number is out of range of float-point. So I wanna replace those values with 0.
Generally speaking, you can find all the elements to replace by:
idx = (I == x); % # x is the "null" value
where I is your image and x is the desired value to replace (in your case, that is the "null" value). However, a more practical syntax would be using a certain threshold value instead of the exact value:
idx = (I > y); % # y is a value much lower than x
Now idx holds the logical indices of the elements you want to zero out. After you obtain idx, just do:
I(idx) = 0;
P.S
In practice, you can do achieve the same result without creating a temporary variable idx, like so:
I(I > y) = 0;