ZKP, Gnark: Does AssertIsLessOrEqual work with negative numbers? - zkp

Does gnarks (ZeroKnowledgeProof framework) AssertIsLessOrEqual work with negative numbers and ecc.BN254 curve?
https://pkg.go.dev/github.com/consensys/gnark#v0.7.0/frontend
It seems most computations including multiplication works with negative numbers but AssertIsLessOrEqual does not work as expected when it has negative parameters.

gnark/bn254 works with unsigned numbers. When you pass -3 then it is 21888242871839275222246405745257275088548364400416034343698204186575808495614
What may mislead as frontend.API.Println will print 21888242871839275222246405745257275088548364400416034343698204186575808495614 as -3
AssertIsLessOrEqual will consider -3 as 21888242871839275222246405745257275088548364400416034343698204186575808495614

Related

bin2dec for 16 bit signed binary values (in google sheets)

In google sheets, I'm trying to convert a 16-bit signed binary number to its decimal equivalent, but the built in function that does that only takes up to 10 bits. Other solutions to the problem that I've seen don't preserve the signedness.
So far I've tried:
bin2dec on the leftmost 8 bits * 2^8 + bin2dec on the rightmost 8 bits
hex2dec on the result of bin2dec on the leftmost 8 bits concatenated with bin2dec on the rightmost 8 bits
I've also seen a suggestion that multiplies each bit by its power of 2, eliminating bin2dec altogether.
Any suggestions?
You will need to use a custom function
function binary2decimal(bin) {
return parseInt(bin, 2);
}
Let's assume that your binary number is in cell A2.
First, set the formatting as follows: Format > Number > Plain text.
Then place the following formula in, say, B2:
=ArrayFormula(SUM(SPLIT(REGEXREPLACE(SUBSTITUTE(A2&"","-",""),"(\d)","$1|"),"|")*(2^SEQUENCE(1,LEN(SUBSTITUTE(A2&"","-","")),LEN(SUBSTITUTE(A2&"","-",""))-1,-1))*IF(LEFT(A2)="-",-1,1)))
This formula will process any length binary number, positive or negative, from 1 bit to 16 bits (and, in fact, to a length of 45 or 46 bits).
What this formula does is SPLIT the binary number (without the negative sign if it exists) into its separate bits, one per column; multiply each of those by 2 raised to the power of each element of an equal-sized degressive SEQUENCE that runs from a high of the LEN (i.e., number) of bits down to zero; and finally apply the negative sign conditionally IF one exists.
If you need to process a range where every value is a positive or negative binary number with exactly 16 bits, you can do so. Suppose that your 16-bit binary numbers are in the range A2:A. First, be sure to select all of Column A and set the formatting to "Plain text" as described above. Then place the following array formula into, say, B2 (being sure that B2:B is empty first):
=ArrayFormula(MMULT(SPLIT(REGEXREPLACE(SUBSTITUTE(FILTER(A2:A,A2:A<>"")&"","-",""),"(\d)","$1|"),"|")*(2^SEQUENCE(1,16,15,-1)),SEQUENCE(16,1,1,0))*IF(LEFT(FILTER(A2:A,A2:A<>""))="-",-1,1))

Unexpected result subtracting decimals in ruby [duplicate]

Can somebody explain why multiplying by 100 here gives a less accurate result but multiplying by 10 twice gives a more accurate result?
± % sc
Loading development environment (Rails 3.0.1)
>> 129.95 * 100
12994.999999999998
>> 129.95*10
1299.5
>> 129.95*10*10
12995.0
If you do the calculations by hand in double-precision binary, which is limited to 53 significant bits, you'll see what's going on:
129.95 = 1.0000001111100110011001100110011001100110011001100110 x 2^7
129.95*100 = 1.1001011000010111111111111111111111111111111111111111011 x 2^13
This is 56 significant bits long, so rounded to 53 bits it's
1.1001011000010111111111111111111111111111111111111111 x 2^13, which equals
12994.999999999998181010596454143524169921875
Now 129.95*10 = 1.01000100110111111111111111111111111111111111111111111 x 2^10
This is 54 significant bits long, so rounded to 53 bits it's 1.01000100111 x 2^10 = 1299.5
Now 1299.5 * 10 = 1.1001011000011 x 2^13 = 12995.
First off: you are looking at the string representation of the result, not the actual result itself. If you really want to compare the two results, you should format both results explicitly, using String#% and you should format both results the same way.
Secondly, that's just how binary floating point numbers work. They are inexact, they are finite and they are binary. All three mean that you get rounding errors, which generally look totally random, unless you happen to have memorized the entirety of IEEE754 and can recite it backwards in your sleep.
There is no floating point number exactly equal to 129.95. So your language uses a value which is close to it instead. When that value is multiplied by 100, the result is close to 12995, but it just so happens to not equal 12995. (It is also not exactly equal to 100 times the original value it used in place of 129.95.) So your interpreter prints a decimal number which is close to (but not equal to) the value of 129.95 * 100 and which shows you that it is not exactly 12995. It also just so happens that the result 129.95 * 10 is exactly equal to 1299.5. This is mostly luck.
Bottom line is, never expect equality out of any floating point arithmetic, only "closeness".

How do I round a positive float up the next integer?

I need to round a positive float upwards to the nearest integer.
examples;
1.0 rounds up to 1
2.1 rounds up to 3
3.5 rounds up to 4
4.9 rounds up to 5
i.e. always round up.
Use the Ceil function from the Math unit. From the documentation:
Rounds variables up toward positive infinity.
Call Ceil (as in ceiling) to obtain the lowest integer greater than or
equal to X. The absolute value of X must be less than MaxInt. For
example:
Ceil(-2.8) = -2
Ceil(2.8) = 3
Ceil(-1.0) = -1
I cannot tell whether or not the behaviour of Ceil meets your expectations for negative input values, because you did not specify what to do there. However, if Ceil does not meet your expectations, it is easy enough to write a function to meet your needs, by combining Abs() and Ceil()
FindField('QTY').ASFLOAT := TRUNC(FindField('QTY').ASFLOAT) + 1
Works Fine

Actionscript rounding bug when dividing then multiplying

I am doing the following in actionscript in Coldfusion Flash Forms:
90 / 3.7
Gives me:
24.3243243243243
Whereas the calculator gives me:
24.32432432432432
Note the extra 2 at the end.
So my problem occurs when I am trying to get the original value of 90 by taking the 24.3243243243243 * 3.7 and then I get 89.9999999999 which is wrong.
Why is Actionscript truncating the value and how do I avoid this so I get the proper amount that the calculator gets?
Thanks so much.
Round your number using a routine like this
var toFixed:Function = function(number, factor) {
return (Math.round(number * factor)/factor);
}
Where the factor is 10, 100, 1000 etc, a simple way to think about it is the number of 0's in the factor is the number of decimal places
so
toFixed(1.23341230123, 100) = 1.23
Good explanation of numeric in ActionScript can be found at http://docstore.mik.ua/orelly/web2/action/ch04_03.htm. See section 4.3.2.1. Floating-point precision
A relavant quote:
"In order to accommodate for the minute discrepancy, you should round your numbers manually if the difference will adversely affect the behavior of your code. "

Small numbers in Objective C 2.0

I created a calculator class that does basic +,-, %, * and sin, cos, tan, sqrt and other math functions.
I have all the variables of type double, everything is working fine for big numbers, so I can calculate numbers like 1.35E122, but the problem is with extremely small numbers. For example if I do calculation 1/98556321 I get 0 where I would like to get something 1.01464E-8.
Should I rewrite my code so that I only manipulate NSDecimalNumber's and if so, what do I do with sin and cos math functions that accept only double and long double values.
1/98556321
This division gives you 0 because integer division is performed here - the result is an integer part of division. The following line should give you floating point result:
1/(double)98556321
integer/integer is always an integer
So either you convert the upper or the lower number to decimal
(double)1/98556321
or
1/(double)98556321
Which explicitely convert the number to double.
Happy coding....

Resources