Difference between = and <=> in extended implicit function definition - vdm++

I see some interesting behaviour with an extended explicit function.
I define an implicit function
isLeap (year:nat) res:bool
post res = year rem 4 = 0 and (year rem 100 = 0 => year rem 400 = 0);
And a corresponding explicit function (since the post condition is computable)
isLeap2 : nat -> bool
isLeap2 (year) == year rem 4 = 0 and (year rem 100 = 0 => year rem 400 = 0);
isLeap2 returns values expected. Then I define an extended implicit function
isLeap (year:nat) res:bool
== year rem 4 = 0 and (year rem 100 = 0 => year rem 400 = 0)
post res = year rem 4 = 0 and (year rem 100 = 0 => year rem 400 = 0);
This works as expected except when provided with an argument that is a multiple of 100 but not 400. The result is
Error 4056: Postcondition failure: post_isLeap in 'test' (/Users/paul/Documents/Overture/workspace/test/test.vdmsl) at line 8:31
Then as I was typing this in I thought, what about
isLeap (year:nat) res:bool
== year rem 4 = 0 and (year rem 100 = 0 => year rem 400 = 0)
post res <=> year rem 4 = 0 and (year rem 100 = 0 => year rem 400 = 0);
and the result is as expected. What is the difference between '=' and '<=>' in this context? In section 3.1.1 of VDM-10 Language Manual (issue Nov 2014) is states "Semantically <=> and = are equivalent when we deal with boolean values." Are they different operationally?

The answer of course is operator precedence. If I parenthesise the first version all is well.
post res = (year rem 4 = 0 and (year rem 100 = 0 => year rem 400 = 0));

Related

Is there a simple (possibly obfuscated) math expression for the number of days in a given month?

For use in cases where a standard library is not available. Assume that the month is given as an unsigned integer.
I'd be interested in seeing the shortest arithmetic expression that gives the correct answer, allowing or disallowing bitwise operators & masks but not lookup tables. Partial expressions can be saved into a variable for readability to showcase the idea used.
Here's an approach that uses only four simple arithmetic and bitwise ops and a 26-bit constant:
int days_in_month(unsigned m) {
// 121110 9 8 7 6 5 4 3 2 1 0
return 28 + ((0b11101110111110111011001100u >> m * 2u) & 0b11);
}
If you also want to handle leap year (no mention of it in the question), you can take a similar approach, at the cost of a few more operations and a 50-bit constant:
int days_in_month2(unsigned m, bool ly) {
return 28 + ((0b11101110111110111011011111101110111110111011001100u >> (m + 12*ly) * 2u) & 0b11);
}
If you are willing the pass the leap year in a different way, e.g., setting a bit like month | 16 to indicate leap year, it would be more efficient.
I assume you pass the month as 1 to 12, not 0 to 11.
Tests and generated asm can be seen on godbolt.
Variation om #BeeOnRope nice answer.
#include <stdbool.h>
int DaysPerMonth(int Month, bool IsLeapYear) {
assert(Month >= 1 && Month <= 12);
// 0b11101110111110111011001100u
// 3 B B E E C C
return (((0x3BBEECCu | (IsLeapYear << 2*2)) >> Month*2) & 3) + 28;
}
#include <stdio.h>
int main() {
for (int ly = 0; ly <= 1; ly++) {
for (int m = 1; m <= 12; m++) {
printf("(%2d %2d), ", m, DaysPerMonth(m,ly));
}
puts("");
}
return 0;
}
Brute force answer in pseudocode for readability:
monthlength(month,is_leapyear) :=
oddmonth = ( month + (month >= 8) ? 1 : 0) % 2 // Or (month ^ (month >> 3))&1
feb_days_offset = (month == 2) ? 2 - is_leapyear : 0
return 30 + oddmonth - feb_days_offset
Where month >= 8 can also be implemented with a bitshift since it's just the fourth bit in an unsigned representation, so that oddmonth is (first bit) xor (fourth bit), which can be consisely written as (month ^ (month >> 3))&1 . Similarly, subtracting the feb offset can be thought of as flipping the second bit on febuary, and flipping the first bit during leap year february.
single line with no intermediate variables:
monthlength(month,isleapyear) := 30 + ( month + (month >= 8 ? 1 : 0)) % 2 - (month==2 ? (2 - isleapyear) : 0)
Alternatively, one that uses exclusively bitwise arithmetic and shifts using the tricks discussed above:
monthlength(month,leapyear) := 30 ^ (month==2)<<1 ^ (month==2)&leapyear ^ (month^month>>3)&1
unsigned int m, leapyr, y ;
//m = month range is 1 to 12
//y = year range is 00 to 99
leapyr = ( ( y & 0x03 ) && 1 ); //0 means leap year and 1 means Non leap year
m = 30 + ( ( m & 1 ) ^ ( 1 && ( m & 8 ) ) ) - ( ( !( m & 13 ) ) ) - ( ( !( m & 13 ) ) & leapyr );
My answer is considering year. If you don't want to use assign leapyr variable 0 or 1 as you wish.

Why is year returning value of 1 when it should be increasing with each loop?

If a flower grows 1cm every year, how long will it take to be 15.24cm?
var year = 0
var length = 0.0
while length <= 15.24 {
if length.truncatingRemainder(dividingBy: 1.0) == 0 {
year += 1
}
length += 0.01
}
print(year)
My approach:
Year increments by 1 each time the length is a whole number (because rate is 1cm/year)
Goal is to calculate how long it'll take to be fully grown (15.24cm)
Year should return 15
Why's it only returning 1?
An example of scaled Int:
var year = 0
var length: Int = 0_00 //1_00 represents 1.00 cm
while length <= 15_24 {
if length % 1_00 == 0 {
year += 1
}
length += 0_01
}
print(year) //-> 16
(Underscores (_) are ignored in Swift numeric literals, it's added just for readability.)
Seems you need to modify a little bit, if you expect 15.

Passing value with numeric format

i have problems regarding passing value with formatting issues.
The description i have put in the codes as i am having problem passing my PreEditedCheque in my code for the if ValidateMMonCheque <> MM part. The output for if length(RawChequenumber) = 15 will be in 1 digit instead of 00001 ( example)
MM = HostGetFLD('','MM')
YY = HostGetFLD('','YY')
PreEditedCheque = substr(RawChequenumber,11,5)
ValidateMMonCheque = substr(RawChequenumber,7,2)
if ValidateMMonCheque <> MM Then *From this statement*
Do
PreEditedCheque = substr('00000',1,5) *This part where those 0 can't be properly shown if pass to the next statement*
EditedCheque = '00'||'2'||'0'||YY||MM||'00'||PreEditedCheque
rc = message(2,2,EditedCheque)
End
if length(RawChequenumber) = 15 Then
EditedCheque = '00'||'2'||'0'||YY||MM||'00'||PreEditedCheque + 1 *Second statement if <>MM ran, this part, the PreEditedCheque will be not in 00001, it will be 1.
rc = PanSetCtlData('PREVIEW',EditedCheque)
What you're asking for is to have the cheque number padded to the left with zeroes in a 5-character field. The Right() function is your friend:
Right(PreEditedCheque, 5, '0') /* "1" -> "00001" */

why passing the return value of an asNumber'ed string breaks io?

I just started the matasano security challenge, and thought about learning IO at the same time.
So now, i'm stuck on challenge 1 where I need to convert a string to base64.
Anyway i've come to the point where i need to convert from binary to decimal, here is my aproach:
binToDec := method( bin, <-- program does not enter this method
dec := 0
rem := 0
i := 0
while ( bin != 0,
rem = bin % 10
bin = bin / 10
dec = dec + rem * 2 pow( i )
i = i + 1
)
return dec
)
toBase64Ascii := method( slice,
tmp := ""
for( a, 0, slice size, <-- construct a string to use with asNumber
tmp = tmp .. slice at( a )
)
dec := binToDec( tmp asNumber ) <-- the line that make the whole thing crash
)
for ( a, 0, bin size, 6,
tmp := toBase64Ascii( bin slice( a, a + 6 )
***some more code***
)
there is no error message or anything, the program just hangs indefinitely.
From the documentation:
asNumber
Returns the receiver converted to a number. Initial whitespace is ignored.
So i must say i'm quite confused here, what is happening ?
I would have done some more research but io is imposible to google for...
I'm not sure what the expected input and output of your binToDec method is, but
while ( bin != 0,
rem = bin % 10
bin = bin / 10
dec = dec + rem * 2 pow( i )
i = i + 1
)
is likely an infinite loop. bin is a floating point number which is repeatedly divided by 10, which does not mean that it ever reaches 0.
I need to convert a string to base64.
Notice that there are asBase64 and fromBase64 methods on sequences.

how to get the range date in vb6

i have 2 date picker
Dim pday, eitday, otherday, tpenalty, difday, subpenalty As Integer
difday = Val(L1.Caption) - Val(L2.Caption)
pday = 7
eitday = 8
otherday = difday - eitday
tpenalty = 25
If difday <= pday Then
PENALTY.Caption = 0
ElseIf difday = eitday Then
PENALTY.Caption = tpenalty
ElseIf difday > eitday Then
For i = 0 To otherday - 1
subpenalty = subpenalty + 5
Next i
PENALTY.Caption = tpenalty + subpenalty
End If
the problem is when the month is change the calculation is invalid.
I'm guessing based on your code (as many things are unclear), but this should give the number of days between two dates:
difday = DateDiff("d", StartDate, EndDate)
I've used StartDate and EndDate to signify the start and end of the lone period which are used to set L1 and L2, as you shouldn't be converting from strings to dates for calculations.