Log in

View Full Version : Make 1 decimal on float


anton_foy
16th July 2022, 19:39
Here I have a part of my script but I get 6 decimals (e.g. 1.123456) and I only want 1 (e.g. 1.1). Is this possible somehow?

in = levels(6*256,1,122*256,0,255*256)

t=ScriptClip(function[in] () {

nTH = in.YDifferenceToNext()
s = float(nTH*0.00009)

Subtitle("Noise=" + String(s), align=2)
} )
t

Julek
16th July 2022, 20:09
flt1 = 1.123456

int1 = Floor(flt1*10) #or Round(flt1*10)
flt2 = Float(int1)/10 #= 1.1000000

Dogway
16th July 2022, 20:38
You can use String() to format to one decimal with rounding.
I made a wrapper for that: nmod(num, dec=1)

I see you directly want it for subtitle, so just use straight String()
Subtitle("Noise=" + String(s,"%0.1f"), align=2)

anton_foy
16th July 2022, 20:56
Thank you both!

@Julek
I get without any decimal (in this case: 2) when trying s = floor(nth*0.00009)


And with this s = float(nth)/10009 I get: 2.315716

@Dogway
Great in which package can I find this wrapper function? Actually I need this for TemporalDegrain2 to dynamically adjust postSigma, in this example I just wanted to see the result shown as a string.

EDIT: Now I tried this: s = nmod(nTH*0.00009, dec=1) but it gives me: 2.100000.
Maybe this is fine to feed to postsigma?

hello_hello
17th July 2022, 10:34
If you always want one decimal place, use Dogway's suggestion and set it with the string() function, but for possible future use, here's a function for formatting numerical strings. The original idea was for the function to remove unnecessary trailing zeros, so as a result you can set the maximum number of decimal places, but it's only a maximum. I don't know if using a function like this inside ScriptClip would slow it down much.

The Limit argument sets the maximum number of decimal places (up to 6). Limit=3 is the default, but that's easy to change if you wish.
Keep=true is for when you always want at least one decimal place, so it ensures a zero after the decimal point is kept or it's added if necessary (unless Limit=0).
The TextA and TextB arguments allow the insertion of text before and after the number being converted to a string, as you'd normally be able to do with the string() function.
The function also removes any negative sign from zero, so -0.0 would display as 0.0

Format String.avsi (https://files.videohelp.com/u/210984/Format%20String.avsi)

Some examples.
A = 72.00667
FormatStr(A) # 72.007
FormatStr(A, limit=2) # 72.01
FormatStr(A, limit=1) # 72
FormatStr(A, limit=1, keep=true) # 72.0

A = 1.00004
string(A, "%.6f") # 1.000040
FormatStr(A, limit=6) # 1.00004
string(A, "%.4f") # 1.0000
FormatStr(A, limit=4) # 1
FormatStr(A, limit=4, keep=true) # 1.0

A = -0.0005
string(A, "%.2f") # -0.00
FormatStr(A, limit=2) # 0
FormatStr(A, limit=2, keep=true) # 0.0

A = 1280.0
B = 720.0
# Displays - Resolution: 1280 x 720
subtitle(string(A, "Resolution: %.0f x ") + string(B, "%.0f"))

# Displays - Resolution: 1280.00 x 720.00
subtitle(string(A, "Resolution: %.2f") + string(B, " x %.2f"))

# Displays - Resolution: 1280 x 720
subtitle(FormatStr(A, "Resolution: ", " x ") + FormatStr(B))

# Displays - Resolution: 1280.0 x 720.0
subtitle(FormatStr(A, "Resolution: ", Keep=true) + FormatStr(B, " x ", Keep=true))

StainlessS
17th July 2022, 14:56
This (StrFmt) was a "special", ripped out of RT_Stats whosit [In RT_stats named RT_String() ].

@MediaFire below this post. [StrFmt_25&26_x86_x64_dll_v1.00_20190114.zip, 72KB, incl 3 * dll + source + VS2008 Project files]
Or Here:- https://www.mediafire.com/file/nhu73fxy7rcvl9q/StrFmt_25%252626_x86_x64_dll_v1.00_20190114.zip/file


StrFmt(String format, dat1,...,datn)

dll's for avs v2.58 & v2.60 x86 & x64.

Returns a formatted string. The unnamed 'format' string and optional unnamed 'dat' args are used to construct the text string that is
returned, uses C/CPP printf() style formatting.
Format: compulsory string controlling format and describing the datn type args that are expected.
datn: Variable number of data args of any type (excluding clip).

printf Format spec here:- http://msdn.microsoft.com/en-us/library/56e442dc%28v=vs.71%29.aspx # M$ Link Now BAD
NOTE, the only support for printing Bool variables is %s as string, ie prints "True" or "False".

Formatting supported, %[flags] [width] [.precision] type

flags, one of "-,+,0, ,#"
width, integer, "*" supported (width supplied via dat arg).
Precision, integer, "*" supported (precision supplied via dat arg).
type,
"c,C,d,i,o,u,x,X", Integer type, c,C=character, d,i=signed, o,u,x,X=unsigned (o=octal, x=Hex).
"e,E,f,g,G", Floating point type
"s,S", String type (also Bool).

Formatting Insertion point is marked with '%' character in the format string (as in Avisynth String function), if you wish to use
a percent character within the returned string, it should be inserted twice in the format string ie '%%' will produce a single '%'.
The data datn arg strings do not require a double '%' character.

A Backslash character '\' introduces escape sequences, to insert a backslash character itself, you must supply a double
backslash sequence ie '\\'.
Converts embedded escape character sequences (Case Significant):-
'\\' Converted to '\' Single Backslash
'\n' Converted to Chr(10) NewLine
'\r' Converted to Chr(13) Carriage Return
'\t' Converted to Chr(9) Horizontal TAB
'\v' Converted to Chr(11) Vertical TAB
'\f' Converted to Chr(12) FormFeed
'\b' Converted to Chr(8) BackSpace
'\a' Converted to Chr(7) Bell
'\x', where x is ANY OTHER CHARACTER not included above, will be copied verbatim, ie '\x'.

eg
StrFmt("Hello there %s and %s.\nGoodbye %d.","Fred","Ted",2019)
would return same as:- "Hello there Fred and Ted." + Chr(10) + "Goodbye 2019."

*****
*****
*****

StrRep(string source,string find,string replace,bool "sig"=True) # Based on Algorithm by Vampiredom, Gavino & IanB.

String args 'source', 'find' and 'replace' unnamed and compulsory.
Takes a source string, searches for all occurences of find string and replaces the found strings with the replace string.
Can use "" in replace string (only in replace) to delete the found substrings from the source string.
Newlines [Chr(10)] are treated no differently to other characters, and could be replaced/deleted.
'sig' arg,default true is Case Significant. Set false for case insignificant find string.

I only want 1 (e.g. 1.1).

So something like

Subtitle(StrFmt("Noise=%.1f",nTh), align=2)


EDIT: Advanced. [Width and Precision, can be supplied as variable args instead of embedded in format string]

colorbars.killaudio
S = StrFmt("'%0*.*f'",10,3,9999.99)
Subtitle(S) # print '009999.990', ie minimum total length of digits and '.' is 10, with 3 fractional digits.
# RED Asterisk, is replaced with 1st arg '10', BLUE Asterisk is replacedwith 2nd arg '3', actual number to convert is 9999.99.
# The "%0" before minimum total length of digits, means 'pad with leading zeros' (otherwise pad with spaces).
# A "%-" instead of above "%0" would left align the result, space padding on right {in this case padding to 10 characters by the Red asterisk 10 arg}.


EDIT: The given MicroSoft C Printf spec page is broken, so here some others.

https://docs.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-170
https://www.freecodecamp.org/news/format-specifiers-in-c/
https://cplusplus.com/reference/cstdio/printf/

NOTE, the only support for printing Bool variables is %s as string, ie prints "True" or "False".
But can use eg Subtitle(StrFmt("Bool=%.1s",True)) # produces "Bool=T".

EDIT: StrFmt thread:- https://forum.doom9.org/showthread.php?t=174649

anton_foy
17th July 2022, 22:06
This is great stuff thanks guys! So if I get this correctly I can convert to String and remove the excessive zeroes and then back to float to feed to for example FFT3D's sigma?

StainlessS
18th July 2022, 04:47
back to float to feed to for example
yes, maybe this shows use.


MyName = "TEST: "
F = Pi

RT_DebugF("Pi = %s\n",String(F),name=MyName)

For(i=0,6) {
S = FracRoundAsString(F,i)
N = Eval(S)
RT_DebugF("%d] N=%f S='%s'", i, N, S,name=MyName)
}

Return MessageClip("DONE")

Function FracRoundAsString(Float Num,Int "FracDigits") {
FracDigits = Default(FracDigits,1).Max(0) # Int, at least 0
Return StrFmt("%1.*f",FracDigits,Num)
}



# DebugView Result

00000481 0.19399980 TEST: Pi = 3.141593
00000482 0.19410621 TEST:
00000483 0.19422890 TEST: 0] N=3.000000 S='3' # but NOTE here, Eval("3") would result in N = int value 3 [but we have printed N as a float].
00000484 0.19432700 TEST: 1] N=3.100000 S='3.1'
00000485 0.19441921 TEST: 2] N=3.140000 S='3.14'
00000486 0.19451070 TEST: 3] N=3.142000 S='3.142'
00000487 0.19462951 TEST: 4] N=3.141600 S='3.1416'
00000488 0.19472340 TEST: 5] N=3.141590 S='3.14159'
00000489 0.19480871 TEST: 6] N=3.141593 S='3.141593'


EDIT: I've printed N before S as N has constant length so as to maintain formatting.

EDIT: Renamed FracRound() to FracRoundAsString()

hello_hello
18th July 2022, 10:34
anton_foy,
for TemporalDegrain2 it won't matter how many decimal places the value has as long as it accepts float.
If you want to round to a single decimal place anyway, why not use Julek's method?

flt1 = 1.123456

int1 = floor(flt1*10.0) # rounds down to 11
or
int1 = ceil(flt1*10.0) # rounds up to 12
or
int1 = round(flt1*10.0) # rounds to nearest integer so 11

flt2 = int1/10.0 = 1.1000000 (or 1.2000000)

subtitle(string(flt2, "%.1f")) # displays 1.1 (or 1.2)

StainlessS
18th July 2022, 13:34
Julek/Hello*2, fine if always fixed number of fractional digits.
But alternative,


MyName = "TEST2: "
F = Pi

RT_DebugF("Pi = %s\n",String(F),name=MyName)

For(i=0,6) {
Fact = Pow(10,i)
N = Round(F*Fact) / Fact
Fmt = "%1."+String(i)+"f"
S = String(N,Fmt)
RT_DebugF("%d] Fact=%9.1f : Fmt='%s' : N=%f : S='%s'", i, Fact,Fmt, N, S, name=MyName)
}

Return MessageClip("DONE")


__END__


00001043 0.17602471 TEST2: Pi = 3.141593
00001044 0.17610569 TEST2:
00001045 0.17620590 TEST2: 0] Fact= 1.0 : Fmt='%1.0f' : N=3.000000 : S='3'
00001046 0.17626271 TEST2: 1] Fact= 10.0 : Fmt='%1.1f' : N=3.100000 : S='3.1'
00001047 0.17632370 TEST2: 2] Fact= 100.0 : Fmt='%1.2f' : N=3.140000 : S='3.14'
00001048 0.17634501 TEST2: 3] Fact= 1000.0 : Fmt='%1.3f' : N=3.142000 : S='3.142'
00001049 0.17641900 TEST2: 4] Fact= 10000.0 : Fmt='%1.4f' : N=3.141600 : S='3.1416'
00001050 0.17647520 TEST2: 5] Fact= 100000.0 : Fmt='%1.5f' : N=3.141590 : S='3.14159'
00001051 0.17648339 TEST2: 6] Fact=1000000.0 : Fmt='%1.6f' : N=3.141593 : S='3.141593'


EDIT: And in actual use you dont need RT_DebugF() or StrFmt(), and Fact and Fmt can be pre-calculated outside of any eg Scriptclip.

anton_foy
18th July 2022, 15:19
anton_foy,
for TemporalDegrain2 it won't matter how many decimal places the value has as long as it accepts float.
If you want to round to a single decimal place anyway, why not use Julek's method?

flt1 = 1.123456

int1 = floor(flt1*10.0) # rounds down to 11
or
int1 = ceil(flt1*10.0) # rounds up to 12
or
int1 = round(flt1*10.0) # rounds to nearest integer so 11

flt2 = int1/10.0 = 1.1000000 (or 1.2000000)

subtitle(string(flt2, "%.1f")) # displays 1.1 (or 1.2)

Thank you well I learn something new all the time. I was under the inpression that it would slow down when many decimals but apparently not, good news!

hello_hello
18th July 2022, 16:30
Thank you well I learn something new all the time. I was under the inpression that it would slow down when many decimals but apparently not, good news!

As far as I know floating point has a fixed number of digits, even if it's mostly zeros.
https://en.wikipedia.org/wiki/Floating-point_arithmetic#Range_of_floating-point_numbers
So even if you converted a string with a single decimal place to float it'd still have lots of zeros, it's just that by default you only see six of them with string().

For the record, not all numbers can be represented exactly in 32 bit floating point anyway, and is probably one reason why the string function defaults to rounding to 6 decimal places.
One of the examples I used in my first post, 72.00667, converts to this in float.

subtitle(string(72.00667, "%.20f"))

https://i.ibb.co/pWKWnnk/1.png

or a smaller number such as 1.55
subtitle(string(1.55))

https://i.ibb.co/Ycg0MCt/2.png

subtitle(string(1.55, "%.24f"))

https://i.ibb.co/DMFd7BX/3.png

0.00009 from your script
subtitle(string(0.00009, "%.40f"))

https://i.ibb.co/5hy8gKx/4.png

hello_hello
25th July 2022, 20:41
I don't know if anyone was interested in the function I linked to in post #5, but I was playing around with the concept of recursion today and it occurred to me it could be applied to removing trailing zeros for the Format String function, so here's a far less "wordy" version that does exactly the same thing, but without a limitation on the maximum number of decimal places, aside from whatever the maximum is for String().

# ===============================================================================
# Format String
# ===============================================================================

function FormatStr(float F, string "Text1", string "Text2", int "Limit", bool "Keep", int "Width") {

Text1 = default(Text1, "")
Text2 = default(Text2, "")
Limit = abs(default(Limit, 3))
Keep = default(Keep, false)
Width = abs(default(Width, 0))
WidthStr = (Width > 0) ? string(Width) : ""

S = Eval("""string(F, "%""" + WidthStr + "." + string(Limit) + """f")""")
S = (Limit == 0) ? S : RemoveTrailingZeros(S)
SLength = StrLen(S)
NewStr = (Limit == 0) || (FindStr(S, ".") < SLength) ? S : !Keep ? LeftStr(S, SLength - 1) : S + "0"
NewStr = (value(NewStr) == 0) && (FindStr(NewStr, "-") > 0) ? RightStr(NewStr, StrLen(NewStr) - 1) : NewStr

return Text1 + NewStr + Text2 }

function RemoveTrailingZeros(string S) {
ZeroPos = FindStr(S + "x", "0x")
return (ZeroPos == 0) ? S : RemoveTrailingZeros(LeftStr(S, ZeroPos - 1)) }

# ===============================================================================

Edit: Inspired by one of StainlessS's functions above, I added a "Width" argument, then tried to work out how it might be useful, at least for me. To line the numbers up all sexy-like, a fixed width font for the subtitle is probably a prerequisite. Maybe it'll come in handy one day, but just for fun....

BlankClip().Subtitle(\
FormatStr(1.005700, "Some Numbers\n", Width=10) + \
FormatStr(6789, "\n", Width=10) + \
FormatStr(206789.1250, "\n", Width=10) + \
FormatStr(67, "\n", Width=10, Keep=true), \
lsp=10, font="courier_new", x=20, y=20)

https://i.ibb.co/23k9VZp/subtitle.png